blob: 17ffd9c5e09303858257b63f5ebcad569ec9973e [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;
20import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_1;
21import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_2;
Ben Murdoch2384df72019-01-28 16:13:55 +000022import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_STATSD_SAMPLE_RATE;
Ben Murdochc26a5a82019-01-16 10:05:58 +000023import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_1;
24import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_2;
25import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_3;
26import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_4;
27import static android.provider.DeviceConfig.ActivityManager.KEY_USE_COMPACTION;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080028
29import android.app.ActivityManager;
Ben Murdochc26a5a82019-01-16 10:05:58 +000030import android.app.ActivityThread;
Ben Murdochfdc55932019-01-30 10:43:15 +000031import android.os.Debug;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080032import android.os.Handler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080033import android.os.Message;
34import android.os.Process;
35import android.os.SystemClock;
36import android.os.Trace;
Ben Murdochc26a5a82019-01-16 10:05:58 +000037import android.provider.DeviceConfig;
38import android.provider.DeviceConfig.OnPropertyChangedListener;
39import android.text.TextUtils;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080040import android.util.EventLog;
41import android.util.StatsLog;
42
Ben Murdochc26a5a82019-01-16 10:05:58 +000043import com.android.internal.annotations.GuardedBy;
44import com.android.internal.annotations.VisibleForTesting;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080045import com.android.server.ServiceThread;
46
47import java.io.FileOutputStream;
Ben Murdochc26a5a82019-01-16 10:05:58 +000048import java.io.PrintWriter;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080049import java.util.ArrayList;
Ben Murdoch2384df72019-01-28 16:13:55 +000050import java.util.Random;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080051
52public final class AppCompactor {
Tim Murray1cdbd1e2018-12-18 15:18:33 -080053
Ben Murdochc26a5a82019-01-16 10:05:58 +000054 // Phenotype sends int configurations and we map them to the strings we'll use on device,
55 // preventing a weird string value entering the kernel.
56 private static final int COMPACT_ACTION_FILE_FLAG = 1;
57 private static final int COMPACT_ACTION_ANON_FLAG = 2;
58 private static final int COMPACT_ACTION_FULL_FLAG = 3;
Tim Murrayf96451b2019-01-30 18:36:48 -080059 private static final int COMPACT_ACTION_NONE_FLAG = 4;
60 private static final String COMPACT_ACTION_NONE = "";
Ben Murdochc26a5a82019-01-16 10:05:58 +000061 private static final String COMPACT_ACTION_FILE = "file";
62 private static final String COMPACT_ACTION_ANON = "anon";
63 private static final String COMPACT_ACTION_FULL = "all";
64
65 // Defaults for phenotype flags.
66 @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
67 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG;
68 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG;
69 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
70 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
71 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
72 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
Ben Murdoch2384df72019-01-28 16:13:55 +000073 // The sampling rate to push app compaction events into statsd for upload.
74 @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
Ben Murdochc26a5a82019-01-16 10:05:58 +000075
76 @VisibleForTesting
77 interface PropertyChangedCallbackForTest {
78 void onPropertyChanged();
79 }
80 private PropertyChangedCallbackForTest mTestCallback;
81
82 // Handler constants.
Tim Murraybbcbc2c2018-12-20 13:30:59 -080083 static final int COMPACT_PROCESS_SOME = 1;
84 static final int COMPACT_PROCESS_FULL = 2;
85 static final int COMPACT_PROCESS_MSG = 1;
86
87 /**
Tim Murray1cdbd1e2018-12-18 15:18:33 -080088 * This thread must be moved to the system background cpuset.
89 * If that doesn't happen, it's probably going to draw a lot of power.
90 * However, this has to happen after the first updateOomAdjLocked, because
91 * that will wipe out the cpuset assignment for system_server threads.
92 * Accordingly, this is in the AMS constructor.
93 */
94 final ServiceThread mCompactionThread;
95
Ben Murdochc26a5a82019-01-16 10:05:58 +000096 private final ArrayList<ProcessRecord> mPendingCompactionProcesses =
97 new ArrayList<ProcessRecord>();
98 private final ActivityManagerService mAm;
99 private final OnPropertyChangedListener mOnFlagsChangedListener =
100 new OnPropertyChangedListener() {
101 @Override
102 public void onPropertyChanged(String namespace, String name, String value) {
103 synchronized (mPhenotypeFlagLock) {
104 if (KEY_USE_COMPACTION.equals(name)) {
105 updateUseCompaction();
106 } else if (KEY_COMPACT_ACTION_1.equals(name)
107 || KEY_COMPACT_ACTION_2.equals(name)) {
108 updateCompactionActions();
109 } else if (KEY_COMPACT_THROTTLE_1.equals(name)
110 || KEY_COMPACT_THROTTLE_2.equals(name)
111 || KEY_COMPACT_THROTTLE_3.equals(name)
112 || KEY_COMPACT_THROTTLE_4.equals(name)) {
113 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000114 } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
115 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000116 }
117 }
118 if (mTestCallback != null) {
119 mTestCallback.onPropertyChanged();
120 }
121 }
122 };
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800123
Ben Murdochc26a5a82019-01-16 10:05:58 +0000124 private final Object mPhenotypeFlagLock = new Object();
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800125
Ben Murdochc26a5a82019-01-16 10:05:58 +0000126 // Configured by phenotype. Updates from the server take effect immediately.
127 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000128 @VisibleForTesting volatile String mCompactActionSome =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000129 compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
130 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000131 @VisibleForTesting volatile String mCompactActionFull =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000132 compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
133 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000134 @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000135 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000136 @VisibleForTesting volatile long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000137 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000138 @VisibleForTesting volatile long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000139 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000140 @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000141 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000142 private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
143
144 private final Random mRandom = new Random();
145 @GuardedBy("mPhenotypeFlagLock")
146 @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800147
Ben Murdochc26a5a82019-01-16 10:05:58 +0000148 // Handler on which compaction runs.
149 private Handler mCompactionHandler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800150
151 public AppCompactor(ActivityManagerService am) {
152 mAm = am;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800153 mCompactionThread = new ServiceThread("CompactionThread",
154 THREAD_PRIORITY_FOREGROUND, true);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800155 }
156
Ben Murdochc26a5a82019-01-16 10:05:58 +0000157 @VisibleForTesting
158 AppCompactor(ActivityManagerService am, PropertyChangedCallbackForTest callback) {
159 this(am);
160 mTestCallback = callback;
161 }
162
163 /**
164 * Reads phenotype config to determine whether app compaction is enabled or not and
165 * starts the background thread if necessary.
166 */
167 public void init() {
168 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.ActivityManager.NAMESPACE,
169 ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
170 synchronized (mPhenotypeFlagLock) {
171 updateUseCompaction();
172 updateCompactionActions();
173 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000174 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000175 }
Tim Murray0a796c12019-02-05 13:03:16 -0800176 Process.setThreadGroupAndCpuset(mCompactionThread.getThreadId(),
177 Process.THREAD_GROUP_SYSTEM);
178
Ben Murdochc26a5a82019-01-16 10:05:58 +0000179 }
180
181 /**
182 * Returns whether compaction is enabled.
183 */
184 public boolean useCompaction() {
185 synchronized (mPhenotypeFlagLock) {
186 return mUseCompaction;
187 }
188 }
189
190 @GuardedBy("mAm")
191 void dump(PrintWriter pw) {
192 pw.println("AppCompactor settings");
193 synchronized (mPhenotypeFlagLock) {
194 pw.println(" " + KEY_USE_COMPACTION + "=" + mUseCompaction);
195 pw.println(" " + KEY_COMPACT_ACTION_1 + "=" + mCompactActionSome);
196 pw.println(" " + KEY_COMPACT_ACTION_2 + "=" + mCompactActionFull);
197 pw.println(" " + KEY_COMPACT_THROTTLE_1 + "=" + mCompactThrottleSomeSome);
198 pw.println(" " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull);
199 pw.println(" " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome);
200 pw.println(" " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
Ben Murdoch2384df72019-01-28 16:13:55 +0000201 pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000202 }
203 }
204
205 @GuardedBy("mAm")
206 void compactAppSome(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800207 app.reqCompactAction = COMPACT_PROCESS_SOME;
208 mPendingCompactionProcesses.add(app);
209 mCompactionHandler.sendMessage(
210 mCompactionHandler.obtainMessage(
211 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
212 }
213
Ben Murdochc26a5a82019-01-16 10:05:58 +0000214 @GuardedBy("mAm")
215 void compactAppFull(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800216 app.reqCompactAction = COMPACT_PROCESS_FULL;
217 mPendingCompactionProcesses.add(app);
218 mCompactionHandler.sendMessage(
219 mCompactionHandler.obtainMessage(
220 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
221
222 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800223
Ben Murdochc26a5a82019-01-16 10:05:58 +0000224 /**
225 * Reads the flag value from DeviceConfig to determine whether app compaction
226 * should be enabled, and starts/stops the compaction thread as needed.
227 */
228 @GuardedBy("mPhenotypeFlagLock")
229 private void updateUseCompaction() {
230 String useCompactionFlag =
231 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
232 KEY_USE_COMPACTION);
233 mUseCompaction = TextUtils.isEmpty(useCompactionFlag)
234 ? DEFAULT_USE_COMPACTION : Boolean.parseBoolean(useCompactionFlag);
235 if (mUseCompaction && !mCompactionThread.isAlive()) {
236 mCompactionThread.start();
237 mCompactionHandler = new MemCompactionHandler();
238 }
239 }
240
241 @GuardedBy("mPhenotypeFlagLock")
242 private void updateCompactionActions() {
243 String compactAction1Flag =
244 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
245 KEY_COMPACT_ACTION_1);
246 String compactAction2Flag =
247 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
248 KEY_COMPACT_ACTION_2);
249
250 int compactAction1 = DEFAULT_COMPACT_ACTION_1;
251 try {
252 compactAction1 = TextUtils.isEmpty(compactAction1Flag)
253 ? DEFAULT_COMPACT_ACTION_1 : Integer.parseInt(compactAction1Flag);
254 } catch (NumberFormatException e) {
255 // Do nothing, leave default.
256 }
257
258 int compactAction2 = DEFAULT_COMPACT_ACTION_2;
259 try {
260 compactAction2 = TextUtils.isEmpty(compactAction2Flag)
261 ? DEFAULT_COMPACT_ACTION_2 : Integer.parseInt(compactAction2Flag);
262 } catch (NumberFormatException e) {
263 // Do nothing, leave default.
264 }
265
266 mCompactActionSome = compactActionIntToString(compactAction1);
267 mCompactActionFull = compactActionIntToString(compactAction2);
268 }
269
270 @GuardedBy("mPhenotypeFlagLock")
271 private void updateCompactionThrottles() {
272 boolean useThrottleDefaults = false;
273 String throttleSomeSomeFlag =
274 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
275 KEY_COMPACT_THROTTLE_1);
276 String throttleSomeFullFlag =
277 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
278 KEY_COMPACT_THROTTLE_2);
279 String throttleFullSomeFlag =
280 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
281 KEY_COMPACT_THROTTLE_3);
282 String throttleFullFullFlag =
283 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
284 KEY_COMPACT_THROTTLE_4);
285
286 if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
287 || TextUtils.isEmpty(throttleFullSomeFlag)
288 || TextUtils.isEmpty(throttleFullFullFlag)) {
289 // Set defaults for all if any are not set.
290 useThrottleDefaults = true;
291 } else {
292 try {
293 mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag);
294 mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag);
295 mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag);
296 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
297 } catch (NumberFormatException e) {
298 useThrottleDefaults = true;
299 }
300 }
301
302 if (useThrottleDefaults) {
303 mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
304 mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
305 mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
306 mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
307 }
308 }
309
Ben Murdoch2384df72019-01-28 16:13:55 +0000310 @GuardedBy("mPhenotypeFlagLock")
311 private void updateStatsdSampleRate() {
312 String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
313 KEY_COMPACT_STATSD_SAMPLE_RATE);
314 try {
315 mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag)
316 ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag);
317 } catch (NumberFormatException e) {
318 mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
319 }
320 mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
321 }
322
Ben Murdochc26a5a82019-01-16 10:05:58 +0000323 @VisibleForTesting
324 static String compactActionIntToString(int action) {
325 switch(action) {
Tim Murrayf96451b2019-01-30 18:36:48 -0800326 case COMPACT_ACTION_NONE_FLAG:
327 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000328 case COMPACT_ACTION_FILE_FLAG:
329 return COMPACT_ACTION_FILE;
330 case COMPACT_ACTION_ANON_FLAG:
331 return COMPACT_ACTION_ANON;
332 case COMPACT_ACTION_FULL_FLAG:
333 return COMPACT_ACTION_FULL;
334 default:
Tim Murrayf96451b2019-01-30 18:36:48 -0800335 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000336 }
337 }
338
339 private final class MemCompactionHandler extends Handler {
340 private MemCompactionHandler() {
341 super(mCompactionThread.getLooper());
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800342 }
343
344 @Override
345 public void handleMessage(Message msg) {
346 switch (msg.what) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000347 case COMPACT_PROCESS_MSG: {
348 long start = SystemClock.uptimeMillis();
349 ProcessRecord proc;
350 int pid;
351 String action;
352 final String name;
353 int pendingAction, lastCompactAction;
354 long lastCompactTime;
355 synchronized (mAm) {
356 proc = mPendingCompactionProcesses.remove(0);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800357
Ben Murdochc26a5a82019-01-16 10:05:58 +0000358 // don't compact if the process has returned to perceptible
359 if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
360 return;
361 }
362
363 pid = proc.pid;
364 name = proc.processName;
365 pendingAction = proc.reqCompactAction;
366 lastCompactAction = proc.lastCompactAction;
367 lastCompactTime = proc.lastCompactTime;
368 }
369
370 if (pid == 0) {
371 // not a real process, either one being launched or one being killed
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800372 return;
373 }
374
Ben Murdochc26a5a82019-01-16 10:05:58 +0000375 // basic throttling
376 // use the Phenotype flag knobs to determine whether current/prevous
377 // compaction combo should be throtted or not
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800378
Ben Murdochc26a5a82019-01-16 10:05:58 +0000379 // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
380 // should very seldom change, and taking the risk of using the wrong action is
381 // preferable to taking the lock for every single compaction action.
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800382 if (pendingAction == COMPACT_PROCESS_SOME) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000383 if ((lastCompactAction == COMPACT_PROCESS_SOME
384 && (start - lastCompactTime < mCompactThrottleSomeSome))
385 || (lastCompactAction == COMPACT_PROCESS_FULL
386 && (start - lastCompactTime
387 < mCompactThrottleSomeFull))) {
388 return;
389 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800390 } else {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000391 if ((lastCompactAction == COMPACT_PROCESS_SOME
392 && (start - lastCompactTime < mCompactThrottleFullSome))
393 || (lastCompactAction == COMPACT_PROCESS_FULL
394 && (start - lastCompactTime
395 < mCompactThrottleFullFull))) {
396 return;
397 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800398 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000399
400 if (pendingAction == COMPACT_PROCESS_SOME) {
401 action = mCompactActionSome;
402 } else {
403 action = mCompactActionFull;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800404 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000405
Tim Murrayf96451b2019-01-30 18:36:48 -0800406 if (action.equals(COMPACT_ACTION_NONE)) {
407 return;
408 }
409
Ben Murdochc26a5a82019-01-16 10:05:58 +0000410 try {
411 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
412 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
413 + ": " + name);
Ben Murdochfdc55932019-01-30 10:43:15 +0000414 long zramFreeKbBefore = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000415 long[] rssBefore = Process.getRss(pid);
416 FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
417 fos.write(action.getBytes());
418 fos.close();
419 long[] rssAfter = Process.getRss(pid);
420 long end = SystemClock.uptimeMillis();
421 long time = end - start;
Ben Murdochfdc55932019-01-30 10:43:15 +0000422 long zramFreeKbAfter = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000423 EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
424 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
425 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
Ben Murdochfdc55932019-01-30 10:43:15 +0000426 lastCompactAction, lastCompactTime, msg.arg1, msg.arg2,
427 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000428 // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
429 // on every single compaction for a flag that will seldom change and the
430 // impact of reading the wrong value here is low.
431 if (mRandom.nextFloat() < mStatsdSampleRate) {
432 StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
433 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
434 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
435 lastCompactAction, lastCompactTime, msg.arg1,
Ben Murdochfdc55932019-01-30 10:43:15 +0000436 ActivityManager.processStateAmToProto(msg.arg2),
437 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000438 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000439 synchronized (mAm) {
440 proc.lastCompactTime = end;
441 proc.lastCompactAction = pendingAction;
442 }
443 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
444 } catch (Exception e) {
445 // nothing to do, presumably the process died
446 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
447 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800448 }
449 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800450 }
451 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800452}