blob: 1f2116065bc181bf2aa18fb208b069875415bd31 [file] [log] [blame]
Tim Murray1cdbd1e2018-12-18 15:18:33 -08001/*
2 * Copyright (C) 2018 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
17package com.android.server.am;
18
Ben Murdochc26a5a82019-01-16 10:05:58 +000019import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080020
21import android.app.ActivityManager;
Ben Murdochc26a5a82019-01-16 10:05:58 +000022import android.app.ActivityThread;
Ben Murdochfdc55932019-01-30 10:43:15 +000023import android.os.Debug;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080024import android.os.Handler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080025import android.os.Message;
26import android.os.Process;
27import android.os.SystemClock;
28import android.os.Trace;
Ben Murdochc26a5a82019-01-16 10:05:58 +000029import android.provider.DeviceConfig;
30import android.provider.DeviceConfig.OnPropertyChangedListener;
31import android.text.TextUtils;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080032import android.util.EventLog;
33import android.util.StatsLog;
34
Ben Murdochc26a5a82019-01-16 10:05:58 +000035import com.android.internal.annotations.GuardedBy;
36import com.android.internal.annotations.VisibleForTesting;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080037import com.android.server.ServiceThread;
38
39import java.io.FileOutputStream;
Ben Murdochc26a5a82019-01-16 10:05:58 +000040import java.io.PrintWriter;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080041import java.util.ArrayList;
Ben Murdoch2384df72019-01-28 16:13:55 +000042import java.util.Random;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080043
44public final class AppCompactor {
Tim Murray1cdbd1e2018-12-18 15:18:33 -080045
Matt Pape40074da2019-02-12 13:53:26 -080046 // Flags stored in the DeviceConfig API.
47 @VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction";
48 @VisibleForTesting static final String KEY_COMPACT_ACTION_1 = "compact_action_1";
49 @VisibleForTesting static final String KEY_COMPACT_ACTION_2 = "compact_action_2";
50 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1";
51 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
52 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
53 @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
54 @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
55 "compact_statsd_sample_rate";
56
Ben Murdochc26a5a82019-01-16 10:05:58 +000057 // Phenotype sends int configurations and we map them to the strings we'll use on device,
58 // preventing a weird string value entering the kernel.
59 private static final int COMPACT_ACTION_FILE_FLAG = 1;
60 private static final int COMPACT_ACTION_ANON_FLAG = 2;
61 private static final int COMPACT_ACTION_FULL_FLAG = 3;
Tim Murrayf96451b2019-01-30 18:36:48 -080062 private static final int COMPACT_ACTION_NONE_FLAG = 4;
63 private static final String COMPACT_ACTION_NONE = "";
Ben Murdochc26a5a82019-01-16 10:05:58 +000064 private static final String COMPACT_ACTION_FILE = "file";
65 private static final String COMPACT_ACTION_ANON = "anon";
66 private static final String COMPACT_ACTION_FULL = "all";
67
68 // Defaults for phenotype flags.
69 @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
70 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG;
71 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG;
72 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
73 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
74 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
75 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
Ben Murdoch2384df72019-01-28 16:13:55 +000076 // The sampling rate to push app compaction events into statsd for upload.
77 @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
Ben Murdochc26a5a82019-01-16 10:05:58 +000078
79 @VisibleForTesting
80 interface PropertyChangedCallbackForTest {
81 void onPropertyChanged();
82 }
83 private PropertyChangedCallbackForTest mTestCallback;
84
85 // Handler constants.
Tim Murraybbcbc2c2018-12-20 13:30:59 -080086 static final int COMPACT_PROCESS_SOME = 1;
87 static final int COMPACT_PROCESS_FULL = 2;
88 static final int COMPACT_PROCESS_MSG = 1;
89
90 /**
Tim Murray1cdbd1e2018-12-18 15:18:33 -080091 * This thread must be moved to the system background cpuset.
92 * If that doesn't happen, it's probably going to draw a lot of power.
93 * However, this has to happen after the first updateOomAdjLocked, because
94 * that will wipe out the cpuset assignment for system_server threads.
95 * Accordingly, this is in the AMS constructor.
96 */
97 final ServiceThread mCompactionThread;
98
Ben Murdochc26a5a82019-01-16 10:05:58 +000099 private final ArrayList<ProcessRecord> mPendingCompactionProcesses =
100 new ArrayList<ProcessRecord>();
101 private final ActivityManagerService mAm;
102 private final OnPropertyChangedListener mOnFlagsChangedListener =
103 new OnPropertyChangedListener() {
104 @Override
105 public void onPropertyChanged(String namespace, String name, String value) {
106 synchronized (mPhenotypeFlagLock) {
107 if (KEY_USE_COMPACTION.equals(name)) {
108 updateUseCompaction();
109 } else if (KEY_COMPACT_ACTION_1.equals(name)
110 || KEY_COMPACT_ACTION_2.equals(name)) {
111 updateCompactionActions();
112 } else if (KEY_COMPACT_THROTTLE_1.equals(name)
113 || KEY_COMPACT_THROTTLE_2.equals(name)
114 || KEY_COMPACT_THROTTLE_3.equals(name)
115 || KEY_COMPACT_THROTTLE_4.equals(name)) {
116 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000117 } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
118 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000119 }
120 }
121 if (mTestCallback != null) {
122 mTestCallback.onPropertyChanged();
123 }
124 }
125 };
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800126
Ben Murdochc26a5a82019-01-16 10:05:58 +0000127 private final Object mPhenotypeFlagLock = new Object();
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800128
Ben Murdochc26a5a82019-01-16 10:05:58 +0000129 // Configured by phenotype. Updates from the server take effect immediately.
130 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000131 @VisibleForTesting volatile String mCompactActionSome =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000132 compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
133 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000134 @VisibleForTesting volatile String mCompactActionFull =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000135 compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
136 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000137 @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000138 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000139 @VisibleForTesting volatile long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000140 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000141 @VisibleForTesting volatile long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000142 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000143 @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000144 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000145 private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
146
147 private final Random mRandom = new Random();
148 @GuardedBy("mPhenotypeFlagLock")
149 @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800150
Ben Murdochc26a5a82019-01-16 10:05:58 +0000151 // Handler on which compaction runs.
152 private Handler mCompactionHandler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800153
154 public AppCompactor(ActivityManagerService am) {
155 mAm = am;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800156 mCompactionThread = new ServiceThread("CompactionThread",
157 THREAD_PRIORITY_FOREGROUND, true);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800158 }
159
Ben Murdochc26a5a82019-01-16 10:05:58 +0000160 @VisibleForTesting
161 AppCompactor(ActivityManagerService am, PropertyChangedCallbackForTest callback) {
162 this(am);
163 mTestCallback = callback;
164 }
165
166 /**
167 * Reads phenotype config to determine whether app compaction is enabled or not and
168 * starts the background thread if necessary.
169 */
170 public void init() {
Matt Pape40074da2019-02-12 13:53:26 -0800171 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000172 ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
173 synchronized (mPhenotypeFlagLock) {
174 updateUseCompaction();
175 updateCompactionActions();
176 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000177 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000178 }
Tim Murray0a796c12019-02-05 13:03:16 -0800179 Process.setThreadGroupAndCpuset(mCompactionThread.getThreadId(),
180 Process.THREAD_GROUP_SYSTEM);
181
Ben Murdochc26a5a82019-01-16 10:05:58 +0000182 }
183
184 /**
185 * Returns whether compaction is enabled.
186 */
187 public boolean useCompaction() {
188 synchronized (mPhenotypeFlagLock) {
189 return mUseCompaction;
190 }
191 }
192
193 @GuardedBy("mAm")
194 void dump(PrintWriter pw) {
195 pw.println("AppCompactor settings");
196 synchronized (mPhenotypeFlagLock) {
197 pw.println(" " + KEY_USE_COMPACTION + "=" + mUseCompaction);
198 pw.println(" " + KEY_COMPACT_ACTION_1 + "=" + mCompactActionSome);
199 pw.println(" " + KEY_COMPACT_ACTION_2 + "=" + mCompactActionFull);
200 pw.println(" " + KEY_COMPACT_THROTTLE_1 + "=" + mCompactThrottleSomeSome);
201 pw.println(" " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull);
202 pw.println(" " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome);
203 pw.println(" " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
Ben Murdoch2384df72019-01-28 16:13:55 +0000204 pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000205 }
206 }
207
208 @GuardedBy("mAm")
209 void compactAppSome(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800210 app.reqCompactAction = COMPACT_PROCESS_SOME;
211 mPendingCompactionProcesses.add(app);
212 mCompactionHandler.sendMessage(
213 mCompactionHandler.obtainMessage(
214 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
215 }
216
Ben Murdochc26a5a82019-01-16 10:05:58 +0000217 @GuardedBy("mAm")
218 void compactAppFull(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800219 app.reqCompactAction = COMPACT_PROCESS_FULL;
220 mPendingCompactionProcesses.add(app);
221 mCompactionHandler.sendMessage(
222 mCompactionHandler.obtainMessage(
223 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
224
225 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800226
Ben Murdochc26a5a82019-01-16 10:05:58 +0000227 /**
228 * Reads the flag value from DeviceConfig to determine whether app compaction
229 * should be enabled, and starts/stops the compaction thread as needed.
230 */
231 @GuardedBy("mPhenotypeFlagLock")
232 private void updateUseCompaction() {
233 String useCompactionFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800234 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000235 KEY_USE_COMPACTION);
236 mUseCompaction = TextUtils.isEmpty(useCompactionFlag)
237 ? DEFAULT_USE_COMPACTION : Boolean.parseBoolean(useCompactionFlag);
238 if (mUseCompaction && !mCompactionThread.isAlive()) {
239 mCompactionThread.start();
240 mCompactionHandler = new MemCompactionHandler();
241 }
242 }
243
244 @GuardedBy("mPhenotypeFlagLock")
245 private void updateCompactionActions() {
246 String compactAction1Flag =
Matt Pape40074da2019-02-12 13:53:26 -0800247 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000248 KEY_COMPACT_ACTION_1);
249 String compactAction2Flag =
Matt Pape40074da2019-02-12 13:53:26 -0800250 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000251 KEY_COMPACT_ACTION_2);
252
253 int compactAction1 = DEFAULT_COMPACT_ACTION_1;
254 try {
255 compactAction1 = TextUtils.isEmpty(compactAction1Flag)
256 ? DEFAULT_COMPACT_ACTION_1 : Integer.parseInt(compactAction1Flag);
257 } catch (NumberFormatException e) {
258 // Do nothing, leave default.
259 }
260
261 int compactAction2 = DEFAULT_COMPACT_ACTION_2;
262 try {
263 compactAction2 = TextUtils.isEmpty(compactAction2Flag)
264 ? DEFAULT_COMPACT_ACTION_2 : Integer.parseInt(compactAction2Flag);
265 } catch (NumberFormatException e) {
266 // Do nothing, leave default.
267 }
268
269 mCompactActionSome = compactActionIntToString(compactAction1);
270 mCompactActionFull = compactActionIntToString(compactAction2);
271 }
272
273 @GuardedBy("mPhenotypeFlagLock")
274 private void updateCompactionThrottles() {
275 boolean useThrottleDefaults = false;
276 String throttleSomeSomeFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800277 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000278 KEY_COMPACT_THROTTLE_1);
279 String throttleSomeFullFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800280 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000281 KEY_COMPACT_THROTTLE_2);
282 String throttleFullSomeFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800283 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000284 KEY_COMPACT_THROTTLE_3);
285 String throttleFullFullFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800286 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000287 KEY_COMPACT_THROTTLE_4);
288
289 if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
290 || TextUtils.isEmpty(throttleFullSomeFlag)
291 || TextUtils.isEmpty(throttleFullFullFlag)) {
292 // Set defaults for all if any are not set.
293 useThrottleDefaults = true;
294 } else {
295 try {
296 mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag);
297 mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag);
298 mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag);
299 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
300 } catch (NumberFormatException e) {
301 useThrottleDefaults = true;
302 }
303 }
304
305 if (useThrottleDefaults) {
306 mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
307 mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
308 mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
309 mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
310 }
311 }
312
Ben Murdoch2384df72019-01-28 16:13:55 +0000313 @GuardedBy("mPhenotypeFlagLock")
314 private void updateStatsdSampleRate() {
Matt Pape40074da2019-02-12 13:53:26 -0800315 String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdoch2384df72019-01-28 16:13:55 +0000316 KEY_COMPACT_STATSD_SAMPLE_RATE);
317 try {
318 mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag)
319 ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag);
320 } catch (NumberFormatException e) {
321 mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
322 }
323 mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
324 }
325
Ben Murdochc26a5a82019-01-16 10:05:58 +0000326 @VisibleForTesting
327 static String compactActionIntToString(int action) {
328 switch(action) {
Tim Murrayf96451b2019-01-30 18:36:48 -0800329 case COMPACT_ACTION_NONE_FLAG:
330 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000331 case COMPACT_ACTION_FILE_FLAG:
332 return COMPACT_ACTION_FILE;
333 case COMPACT_ACTION_ANON_FLAG:
334 return COMPACT_ACTION_ANON;
335 case COMPACT_ACTION_FULL_FLAG:
336 return COMPACT_ACTION_FULL;
337 default:
Tim Murrayf96451b2019-01-30 18:36:48 -0800338 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000339 }
340 }
341
342 private final class MemCompactionHandler extends Handler {
343 private MemCompactionHandler() {
344 super(mCompactionThread.getLooper());
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800345 }
346
347 @Override
348 public void handleMessage(Message msg) {
349 switch (msg.what) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000350 case COMPACT_PROCESS_MSG: {
351 long start = SystemClock.uptimeMillis();
352 ProcessRecord proc;
353 int pid;
354 String action;
355 final String name;
356 int pendingAction, lastCompactAction;
357 long lastCompactTime;
358 synchronized (mAm) {
359 proc = mPendingCompactionProcesses.remove(0);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800360
Ben Murdochc26a5a82019-01-16 10:05:58 +0000361 // don't compact if the process has returned to perceptible
362 if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
363 return;
364 }
365
366 pid = proc.pid;
367 name = proc.processName;
368 pendingAction = proc.reqCompactAction;
369 lastCompactAction = proc.lastCompactAction;
370 lastCompactTime = proc.lastCompactTime;
371 }
372
373 if (pid == 0) {
374 // not a real process, either one being launched or one being killed
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800375 return;
376 }
377
Ben Murdochc26a5a82019-01-16 10:05:58 +0000378 // basic throttling
379 // use the Phenotype flag knobs to determine whether current/prevous
380 // compaction combo should be throtted or not
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800381
Ben Murdochc26a5a82019-01-16 10:05:58 +0000382 // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
383 // should very seldom change, and taking the risk of using the wrong action is
384 // preferable to taking the lock for every single compaction action.
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800385 if (pendingAction == COMPACT_PROCESS_SOME) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000386 if ((lastCompactAction == COMPACT_PROCESS_SOME
387 && (start - lastCompactTime < mCompactThrottleSomeSome))
388 || (lastCompactAction == COMPACT_PROCESS_FULL
389 && (start - lastCompactTime
390 < mCompactThrottleSomeFull))) {
391 return;
392 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800393 } else {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000394 if ((lastCompactAction == COMPACT_PROCESS_SOME
395 && (start - lastCompactTime < mCompactThrottleFullSome))
396 || (lastCompactAction == COMPACT_PROCESS_FULL
397 && (start - lastCompactTime
398 < mCompactThrottleFullFull))) {
399 return;
400 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800401 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000402
403 if (pendingAction == COMPACT_PROCESS_SOME) {
404 action = mCompactActionSome;
405 } else {
406 action = mCompactActionFull;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800407 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000408
Tim Murrayf96451b2019-01-30 18:36:48 -0800409 if (action.equals(COMPACT_ACTION_NONE)) {
410 return;
411 }
412
Ben Murdochc26a5a82019-01-16 10:05:58 +0000413 try {
414 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
415 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
416 + ": " + name);
Ben Murdochfdc55932019-01-30 10:43:15 +0000417 long zramFreeKbBefore = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000418 long[] rssBefore = Process.getRss(pid);
419 FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
420 fos.write(action.getBytes());
421 fos.close();
422 long[] rssAfter = Process.getRss(pid);
423 long end = SystemClock.uptimeMillis();
424 long time = end - start;
Ben Murdochfdc55932019-01-30 10:43:15 +0000425 long zramFreeKbAfter = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000426 EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
427 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
428 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
Ben Murdochfdc55932019-01-30 10:43:15 +0000429 lastCompactAction, lastCompactTime, msg.arg1, msg.arg2,
430 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000431 // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
432 // on every single compaction for a flag that will seldom change and the
433 // impact of reading the wrong value here is low.
434 if (mRandom.nextFloat() < mStatsdSampleRate) {
435 StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
436 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
437 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
438 lastCompactAction, lastCompactTime, msg.arg1,
Ben Murdochfdc55932019-01-30 10:43:15 +0000439 ActivityManager.processStateAmToProto(msg.arg2),
440 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000441 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000442 synchronized (mAm) {
443 proc.lastCompactTime = end;
444 proc.lastCompactAction = pendingAction;
445 }
446 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
447 } catch (Exception e) {
448 // nothing to do, presumably the process died
449 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
450 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800451 }
452 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800453 }
454 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800455}