blob: 08f1669bb7a20643864e53d3be08054d4e5a76a6 [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() {
Stanislav Zholnin632c91522019-03-07 15:46:27 +0000233 mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
234 KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000235 if (mUseCompaction && !mCompactionThread.isAlive()) {
236 mCompactionThread.start();
237 mCompactionHandler = new MemCompactionHandler();
238 }
239 }
240
241 @GuardedBy("mPhenotypeFlagLock")
242 private void updateCompactionActions() {
Stanislav Zholnin632c91522019-03-07 15:46:27 +0000243 int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
244 KEY_COMPACT_ACTION_1, DEFAULT_COMPACT_ACTION_1);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000245
Stanislav Zholnin632c91522019-03-07 15:46:27 +0000246 int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
247 KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000248
249 mCompactActionSome = compactActionIntToString(compactAction1);
250 mCompactActionFull = compactActionIntToString(compactAction2);
251 }
252
253 @GuardedBy("mPhenotypeFlagLock")
254 private void updateCompactionThrottles() {
255 boolean useThrottleDefaults = false;
256 String throttleSomeSomeFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800257 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000258 KEY_COMPACT_THROTTLE_1);
259 String throttleSomeFullFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800260 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000261 KEY_COMPACT_THROTTLE_2);
262 String throttleFullSomeFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800263 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000264 KEY_COMPACT_THROTTLE_3);
265 String throttleFullFullFlag =
Matt Pape40074da2019-02-12 13:53:26 -0800266 DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
Ben Murdochc26a5a82019-01-16 10:05:58 +0000267 KEY_COMPACT_THROTTLE_4);
268
269 if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
270 || TextUtils.isEmpty(throttleFullSomeFlag)
271 || TextUtils.isEmpty(throttleFullFullFlag)) {
272 // Set defaults for all if any are not set.
273 useThrottleDefaults = true;
274 } else {
275 try {
276 mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag);
277 mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag);
278 mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag);
279 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
280 } catch (NumberFormatException e) {
281 useThrottleDefaults = true;
282 }
283 }
284
285 if (useThrottleDefaults) {
286 mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
287 mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
288 mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
289 mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
290 }
291 }
292
Ben Murdoch2384df72019-01-28 16:13:55 +0000293 @GuardedBy("mPhenotypeFlagLock")
294 private void updateStatsdSampleRate() {
Stanislav Zholnin632c91522019-03-07 15:46:27 +0000295 mStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
296 KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
Ben Murdoch2384df72019-01-28 16:13:55 +0000297 mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
298 }
299
Ben Murdochc26a5a82019-01-16 10:05:58 +0000300 @VisibleForTesting
301 static String compactActionIntToString(int action) {
302 switch(action) {
Tim Murrayf96451b2019-01-30 18:36:48 -0800303 case COMPACT_ACTION_NONE_FLAG:
304 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000305 case COMPACT_ACTION_FILE_FLAG:
306 return COMPACT_ACTION_FILE;
307 case COMPACT_ACTION_ANON_FLAG:
308 return COMPACT_ACTION_ANON;
309 case COMPACT_ACTION_FULL_FLAG:
310 return COMPACT_ACTION_FULL;
311 default:
Tim Murrayf96451b2019-01-30 18:36:48 -0800312 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000313 }
314 }
315
316 private final class MemCompactionHandler extends Handler {
317 private MemCompactionHandler() {
318 super(mCompactionThread.getLooper());
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800319 }
320
321 @Override
322 public void handleMessage(Message msg) {
323 switch (msg.what) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000324 case COMPACT_PROCESS_MSG: {
325 long start = SystemClock.uptimeMillis();
326 ProcessRecord proc;
327 int pid;
328 String action;
329 final String name;
330 int pendingAction, lastCompactAction;
331 long lastCompactTime;
332 synchronized (mAm) {
333 proc = mPendingCompactionProcesses.remove(0);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800334
Ben Murdochc26a5a82019-01-16 10:05:58 +0000335 // don't compact if the process has returned to perceptible
336 if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
337 return;
338 }
339
340 pid = proc.pid;
341 name = proc.processName;
342 pendingAction = proc.reqCompactAction;
343 lastCompactAction = proc.lastCompactAction;
344 lastCompactTime = proc.lastCompactTime;
345 }
346
347 if (pid == 0) {
348 // not a real process, either one being launched or one being killed
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800349 return;
350 }
351
Ben Murdochc26a5a82019-01-16 10:05:58 +0000352 // basic throttling
353 // use the Phenotype flag knobs to determine whether current/prevous
354 // compaction combo should be throtted or not
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800355
Ben Murdochc26a5a82019-01-16 10:05:58 +0000356 // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
357 // should very seldom change, and taking the risk of using the wrong action is
358 // preferable to taking the lock for every single compaction action.
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800359 if (pendingAction == COMPACT_PROCESS_SOME) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000360 if ((lastCompactAction == COMPACT_PROCESS_SOME
361 && (start - lastCompactTime < mCompactThrottleSomeSome))
362 || (lastCompactAction == COMPACT_PROCESS_FULL
363 && (start - lastCompactTime
364 < mCompactThrottleSomeFull))) {
365 return;
366 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800367 } else {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000368 if ((lastCompactAction == COMPACT_PROCESS_SOME
369 && (start - lastCompactTime < mCompactThrottleFullSome))
370 || (lastCompactAction == COMPACT_PROCESS_FULL
371 && (start - lastCompactTime
372 < mCompactThrottleFullFull))) {
373 return;
374 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800375 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000376
377 if (pendingAction == COMPACT_PROCESS_SOME) {
378 action = mCompactActionSome;
379 } else {
380 action = mCompactActionFull;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800381 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000382
Tim Murrayf96451b2019-01-30 18:36:48 -0800383 if (action.equals(COMPACT_ACTION_NONE)) {
384 return;
385 }
386
Ben Murdochc26a5a82019-01-16 10:05:58 +0000387 try {
388 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
389 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
390 + ": " + name);
Ben Murdochfdc55932019-01-30 10:43:15 +0000391 long zramFreeKbBefore = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000392 long[] rssBefore = Process.getRss(pid);
393 FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
394 fos.write(action.getBytes());
395 fos.close();
396 long[] rssAfter = Process.getRss(pid);
397 long end = SystemClock.uptimeMillis();
398 long time = end - start;
Ben Murdochfdc55932019-01-30 10:43:15 +0000399 long zramFreeKbAfter = Debug.getZramFreeKb();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000400 EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
401 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
402 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
Ben Murdochfdc55932019-01-30 10:43:15 +0000403 lastCompactAction, lastCompactTime, msg.arg1, msg.arg2,
404 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000405 // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
406 // on every single compaction for a flag that will seldom change and the
407 // impact of reading the wrong value here is low.
408 if (mRandom.nextFloat() < mStatsdSampleRate) {
409 StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
410 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
411 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
412 lastCompactAction, lastCompactTime, msg.arg1,
Ben Murdochfdc55932019-01-30 10:43:15 +0000413 ActivityManager.processStateAmToProto(msg.arg2),
414 zramFreeKbBefore, zramFreeKbAfter);
Ben Murdoch2384df72019-01-28 16:13:55 +0000415 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000416 synchronized (mAm) {
417 proc.lastCompactTime = end;
418 proc.lastCompactAction = pendingAction;
419 }
420 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
421 } catch (Exception e) {
422 // nothing to do, presumably the process died
423 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
424 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800425 }
426 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800427 }
428 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800429}