blob: c7e4fc78c01308836e93eabf6f9af855884266a0 [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;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080031import android.os.Handler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080032import android.os.Message;
33import android.os.Process;
34import android.os.SystemClock;
35import android.os.Trace;
Ben Murdochc26a5a82019-01-16 10:05:58 +000036import android.provider.DeviceConfig;
37import android.provider.DeviceConfig.OnPropertyChangedListener;
38import android.text.TextUtils;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080039import android.util.EventLog;
40import android.util.StatsLog;
41
Ben Murdochc26a5a82019-01-16 10:05:58 +000042import com.android.internal.annotations.GuardedBy;
43import com.android.internal.annotations.VisibleForTesting;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080044import com.android.server.ServiceThread;
45
46import java.io.FileOutputStream;
Ben Murdochc26a5a82019-01-16 10:05:58 +000047import java.io.PrintWriter;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080048import java.util.ArrayList;
Ben Murdoch2384df72019-01-28 16:13:55 +000049import java.util.Random;
Tim Murray1cdbd1e2018-12-18 15:18:33 -080050
51public final class AppCompactor {
Tim Murray1cdbd1e2018-12-18 15:18:33 -080052
Ben Murdochc26a5a82019-01-16 10:05:58 +000053 // Phenotype sends int configurations and we map them to the strings we'll use on device,
54 // preventing a weird string value entering the kernel.
55 private static final int COMPACT_ACTION_FILE_FLAG = 1;
56 private static final int COMPACT_ACTION_ANON_FLAG = 2;
57 private static final int COMPACT_ACTION_FULL_FLAG = 3;
Tim Murrayf96451b2019-01-30 18:36:48 -080058 private static final int COMPACT_ACTION_NONE_FLAG = 4;
59 private static final String COMPACT_ACTION_NONE = "";
Ben Murdochc26a5a82019-01-16 10:05:58 +000060 private static final String COMPACT_ACTION_FILE = "file";
61 private static final String COMPACT_ACTION_ANON = "anon";
62 private static final String COMPACT_ACTION_FULL = "all";
63
64 // Defaults for phenotype flags.
65 @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
66 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG;
67 @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG;
68 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
69 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
70 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
71 @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
Ben Murdoch2384df72019-01-28 16:13:55 +000072 // The sampling rate to push app compaction events into statsd for upload.
73 @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
Ben Murdochc26a5a82019-01-16 10:05:58 +000074
75 @VisibleForTesting
76 interface PropertyChangedCallbackForTest {
77 void onPropertyChanged();
78 }
79 private PropertyChangedCallbackForTest mTestCallback;
80
81 // Handler constants.
Tim Murraybbcbc2c2018-12-20 13:30:59 -080082 static final int COMPACT_PROCESS_SOME = 1;
83 static final int COMPACT_PROCESS_FULL = 2;
84 static final int COMPACT_PROCESS_MSG = 1;
85
86 /**
Tim Murray1cdbd1e2018-12-18 15:18:33 -080087 * This thread must be moved to the system background cpuset.
88 * If that doesn't happen, it's probably going to draw a lot of power.
89 * However, this has to happen after the first updateOomAdjLocked, because
90 * that will wipe out the cpuset assignment for system_server threads.
91 * Accordingly, this is in the AMS constructor.
92 */
93 final ServiceThread mCompactionThread;
94
Ben Murdochc26a5a82019-01-16 10:05:58 +000095 private final ArrayList<ProcessRecord> mPendingCompactionProcesses =
96 new ArrayList<ProcessRecord>();
97 private final ActivityManagerService mAm;
98 private final OnPropertyChangedListener mOnFlagsChangedListener =
99 new OnPropertyChangedListener() {
100 @Override
101 public void onPropertyChanged(String namespace, String name, String value) {
102 synchronized (mPhenotypeFlagLock) {
103 if (KEY_USE_COMPACTION.equals(name)) {
104 updateUseCompaction();
105 } else if (KEY_COMPACT_ACTION_1.equals(name)
106 || KEY_COMPACT_ACTION_2.equals(name)) {
107 updateCompactionActions();
108 } else if (KEY_COMPACT_THROTTLE_1.equals(name)
109 || KEY_COMPACT_THROTTLE_2.equals(name)
110 || KEY_COMPACT_THROTTLE_3.equals(name)
111 || KEY_COMPACT_THROTTLE_4.equals(name)) {
112 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000113 } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
114 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000115 }
116 }
117 if (mTestCallback != null) {
118 mTestCallback.onPropertyChanged();
119 }
120 }
121 };
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800122
Ben Murdochc26a5a82019-01-16 10:05:58 +0000123 private final Object mPhenotypeFlagLock = new Object();
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800124
Ben Murdochc26a5a82019-01-16 10:05:58 +0000125 // Configured by phenotype. Updates from the server take effect immediately.
126 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000127 @VisibleForTesting volatile String mCompactActionSome =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000128 compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
129 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000130 @VisibleForTesting volatile String mCompactActionFull =
Ben Murdochc26a5a82019-01-16 10:05:58 +0000131 compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
132 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000133 @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000134 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000135 @VisibleForTesting volatile long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000136 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000137 @VisibleForTesting volatile long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000138 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000139 @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000140 @GuardedBy("mPhenotypeFlagLock")
Ben Murdoch2384df72019-01-28 16:13:55 +0000141 private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
142
143 private final Random mRandom = new Random();
144 @GuardedBy("mPhenotypeFlagLock")
145 @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
Tim Murraybbcbc2c2018-12-20 13:30:59 -0800146
Ben Murdochc26a5a82019-01-16 10:05:58 +0000147 // Handler on which compaction runs.
148 private Handler mCompactionHandler;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800149
150 public AppCompactor(ActivityManagerService am) {
151 mAm = am;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800152 mCompactionThread = new ServiceThread("CompactionThread",
153 THREAD_PRIORITY_FOREGROUND, true);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800154 }
155
Ben Murdochc26a5a82019-01-16 10:05:58 +0000156 @VisibleForTesting
157 AppCompactor(ActivityManagerService am, PropertyChangedCallbackForTest callback) {
158 this(am);
159 mTestCallback = callback;
160 }
161
162 /**
163 * Reads phenotype config to determine whether app compaction is enabled or not and
164 * starts the background thread if necessary.
165 */
166 public void init() {
167 DeviceConfig.addOnPropertyChangedListener(DeviceConfig.ActivityManager.NAMESPACE,
168 ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
169 synchronized (mPhenotypeFlagLock) {
170 updateUseCompaction();
171 updateCompactionActions();
172 updateCompactionThrottles();
Ben Murdoch2384df72019-01-28 16:13:55 +0000173 updateStatsdSampleRate();
Ben Murdochc26a5a82019-01-16 10:05:58 +0000174 }
Tim Murray0a796c12019-02-05 13:03:16 -0800175 Process.setThreadGroupAndCpuset(mCompactionThread.getThreadId(),
176 Process.THREAD_GROUP_SYSTEM);
177
Ben Murdochc26a5a82019-01-16 10:05:58 +0000178 }
179
180 /**
181 * Returns whether compaction is enabled.
182 */
183 public boolean useCompaction() {
184 synchronized (mPhenotypeFlagLock) {
185 return mUseCompaction;
186 }
187 }
188
189 @GuardedBy("mAm")
190 void dump(PrintWriter pw) {
191 pw.println("AppCompactor settings");
192 synchronized (mPhenotypeFlagLock) {
193 pw.println(" " + KEY_USE_COMPACTION + "=" + mUseCompaction);
194 pw.println(" " + KEY_COMPACT_ACTION_1 + "=" + mCompactActionSome);
195 pw.println(" " + KEY_COMPACT_ACTION_2 + "=" + mCompactActionFull);
196 pw.println(" " + KEY_COMPACT_THROTTLE_1 + "=" + mCompactThrottleSomeSome);
197 pw.println(" " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull);
198 pw.println(" " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome);
199 pw.println(" " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
Ben Murdoch2384df72019-01-28 16:13:55 +0000200 pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
Ben Murdochc26a5a82019-01-16 10:05:58 +0000201 }
202 }
203
204 @GuardedBy("mAm")
205 void compactAppSome(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800206 app.reqCompactAction = COMPACT_PROCESS_SOME;
207 mPendingCompactionProcesses.add(app);
208 mCompactionHandler.sendMessage(
209 mCompactionHandler.obtainMessage(
210 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
211 }
212
Ben Murdochc26a5a82019-01-16 10:05:58 +0000213 @GuardedBy("mAm")
214 void compactAppFull(ProcessRecord app) {
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800215 app.reqCompactAction = COMPACT_PROCESS_FULL;
216 mPendingCompactionProcesses.add(app);
217 mCompactionHandler.sendMessage(
218 mCompactionHandler.obtainMessage(
219 COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
220
221 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800222
Ben Murdochc26a5a82019-01-16 10:05:58 +0000223 /**
224 * Reads the flag value from DeviceConfig to determine whether app compaction
225 * should be enabled, and starts/stops the compaction thread as needed.
226 */
227 @GuardedBy("mPhenotypeFlagLock")
228 private void updateUseCompaction() {
229 String useCompactionFlag =
230 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
231 KEY_USE_COMPACTION);
232 mUseCompaction = TextUtils.isEmpty(useCompactionFlag)
233 ? DEFAULT_USE_COMPACTION : Boolean.parseBoolean(useCompactionFlag);
234 if (mUseCompaction && !mCompactionThread.isAlive()) {
235 mCompactionThread.start();
236 mCompactionHandler = new MemCompactionHandler();
237 }
238 }
239
240 @GuardedBy("mPhenotypeFlagLock")
241 private void updateCompactionActions() {
242 String compactAction1Flag =
243 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
244 KEY_COMPACT_ACTION_1);
245 String compactAction2Flag =
246 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
247 KEY_COMPACT_ACTION_2);
248
249 int compactAction1 = DEFAULT_COMPACT_ACTION_1;
250 try {
251 compactAction1 = TextUtils.isEmpty(compactAction1Flag)
252 ? DEFAULT_COMPACT_ACTION_1 : Integer.parseInt(compactAction1Flag);
253 } catch (NumberFormatException e) {
254 // Do nothing, leave default.
255 }
256
257 int compactAction2 = DEFAULT_COMPACT_ACTION_2;
258 try {
259 compactAction2 = TextUtils.isEmpty(compactAction2Flag)
260 ? DEFAULT_COMPACT_ACTION_2 : Integer.parseInt(compactAction2Flag);
261 } catch (NumberFormatException e) {
262 // Do nothing, leave default.
263 }
264
265 mCompactActionSome = compactActionIntToString(compactAction1);
266 mCompactActionFull = compactActionIntToString(compactAction2);
267 }
268
269 @GuardedBy("mPhenotypeFlagLock")
270 private void updateCompactionThrottles() {
271 boolean useThrottleDefaults = false;
272 String throttleSomeSomeFlag =
273 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
274 KEY_COMPACT_THROTTLE_1);
275 String throttleSomeFullFlag =
276 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
277 KEY_COMPACT_THROTTLE_2);
278 String throttleFullSomeFlag =
279 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
280 KEY_COMPACT_THROTTLE_3);
281 String throttleFullFullFlag =
282 DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
283 KEY_COMPACT_THROTTLE_4);
284
285 if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
286 || TextUtils.isEmpty(throttleFullSomeFlag)
287 || TextUtils.isEmpty(throttleFullFullFlag)) {
288 // Set defaults for all if any are not set.
289 useThrottleDefaults = true;
290 } else {
291 try {
292 mCompactThrottleSomeSome = Integer.parseInt(throttleSomeSomeFlag);
293 mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag);
294 mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag);
295 mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
296 } catch (NumberFormatException e) {
297 useThrottleDefaults = true;
298 }
299 }
300
301 if (useThrottleDefaults) {
302 mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
303 mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
304 mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
305 mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
306 }
307 }
308
Ben Murdoch2384df72019-01-28 16:13:55 +0000309 @GuardedBy("mPhenotypeFlagLock")
310 private void updateStatsdSampleRate() {
311 String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
312 KEY_COMPACT_STATSD_SAMPLE_RATE);
313 try {
314 mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag)
315 ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag);
316 } catch (NumberFormatException e) {
317 mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
318 }
319 mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
320 }
321
Ben Murdochc26a5a82019-01-16 10:05:58 +0000322 @VisibleForTesting
323 static String compactActionIntToString(int action) {
324 switch(action) {
Tim Murrayf96451b2019-01-30 18:36:48 -0800325 case COMPACT_ACTION_NONE_FLAG:
326 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000327 case COMPACT_ACTION_FILE_FLAG:
328 return COMPACT_ACTION_FILE;
329 case COMPACT_ACTION_ANON_FLAG:
330 return COMPACT_ACTION_ANON;
331 case COMPACT_ACTION_FULL_FLAG:
332 return COMPACT_ACTION_FULL;
333 default:
Tim Murrayf96451b2019-01-30 18:36:48 -0800334 return COMPACT_ACTION_NONE;
Ben Murdochc26a5a82019-01-16 10:05:58 +0000335 }
336 }
337
338 private final class MemCompactionHandler extends Handler {
339 private MemCompactionHandler() {
340 super(mCompactionThread.getLooper());
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800341 }
342
343 @Override
344 public void handleMessage(Message msg) {
345 switch (msg.what) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000346 case COMPACT_PROCESS_MSG: {
347 long start = SystemClock.uptimeMillis();
348 ProcessRecord proc;
349 int pid;
350 String action;
351 final String name;
352 int pendingAction, lastCompactAction;
353 long lastCompactTime;
354 synchronized (mAm) {
355 proc = mPendingCompactionProcesses.remove(0);
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800356
Ben Murdochc26a5a82019-01-16 10:05:58 +0000357 // don't compact if the process has returned to perceptible
358 if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
359 return;
360 }
361
362 pid = proc.pid;
363 name = proc.processName;
364 pendingAction = proc.reqCompactAction;
365 lastCompactAction = proc.lastCompactAction;
366 lastCompactTime = proc.lastCompactTime;
367 }
368
369 if (pid == 0) {
370 // not a real process, either one being launched or one being killed
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800371 return;
372 }
373
Ben Murdochc26a5a82019-01-16 10:05:58 +0000374 // basic throttling
375 // use the Phenotype flag knobs to determine whether current/prevous
376 // compaction combo should be throtted or not
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800377
Ben Murdochc26a5a82019-01-16 10:05:58 +0000378 // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
379 // should very seldom change, and taking the risk of using the wrong action is
380 // preferable to taking the lock for every single compaction action.
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800381 if (pendingAction == COMPACT_PROCESS_SOME) {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000382 if ((lastCompactAction == COMPACT_PROCESS_SOME
383 && (start - lastCompactTime < mCompactThrottleSomeSome))
384 || (lastCompactAction == COMPACT_PROCESS_FULL
385 && (start - lastCompactTime
386 < mCompactThrottleSomeFull))) {
387 return;
388 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800389 } else {
Ben Murdochc26a5a82019-01-16 10:05:58 +0000390 if ((lastCompactAction == COMPACT_PROCESS_SOME
391 && (start - lastCompactTime < mCompactThrottleFullSome))
392 || (lastCompactAction == COMPACT_PROCESS_FULL
393 && (start - lastCompactTime
394 < mCompactThrottleFullFull))) {
395 return;
396 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800397 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000398
399 if (pendingAction == COMPACT_PROCESS_SOME) {
400 action = mCompactActionSome;
401 } else {
402 action = mCompactActionFull;
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800403 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000404
Tim Murrayf96451b2019-01-30 18:36:48 -0800405 if (action.equals(COMPACT_ACTION_NONE)) {
406 return;
407 }
408
Ben Murdochc26a5a82019-01-16 10:05:58 +0000409 try {
410 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
411 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
412 + ": " + name);
413 long[] rssBefore = Process.getRss(pid);
414 FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
415 fos.write(action.getBytes());
416 fos.close();
417 long[] rssAfter = Process.getRss(pid);
418 long end = SystemClock.uptimeMillis();
419 long time = end - start;
420 EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
421 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
422 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
423 lastCompactAction, lastCompactTime, msg.arg1, msg.arg2);
Ben Murdoch2384df72019-01-28 16:13:55 +0000424 // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
425 // on every single compaction for a flag that will seldom change and the
426 // impact of reading the wrong value here is low.
427 if (mRandom.nextFloat() < mStatsdSampleRate) {
428 StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
429 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
430 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
431 lastCompactAction, lastCompactTime, msg.arg1,
432 ActivityManager.processStateAmToProto(msg.arg2));
433 }
Ben Murdochc26a5a82019-01-16 10:05:58 +0000434 synchronized (mAm) {
435 proc.lastCompactTime = end;
436 proc.lastCompactAction = pendingAction;
437 }
438 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
439 } catch (Exception e) {
440 // nothing to do, presumably the process died
441 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
442 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800443 }
444 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800445 }
446 }
Tim Murray1cdbd1e2018-12-18 15:18:33 -0800447}