代码位于frameworks/base/services/core/java/com/android/server/am/,一共有七十个文件。

Java源码位于package com.android.server.am里

下面是消息处理部分

处理应用崩溃消息

 14223    /**
14224 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
14225 * The application process will exit immediately after this call returns.
14226 * @param app object of the crashing app, null for the system server
14227 * @param crashInfo describing the exception
14228 */
14229 public void handleApplicationCrash(IBinder app,
14230 ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
14231 ProcessRecord r = findAppProcess(app, "Crash");
14232 final String processName = app == null ? "system_server"
14233 : (r == null ? "unknown" : r.processName);
14234
14235 handleApplicationCrashInner("crash", r, processName, crashInfo);
14236 }
14237
14238 /* Native crash reporting uses this inner version because it needs to be somewhat
14239 * decoupled from the AM-managed cleanup lifecycle
14240 */
14241 void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName,
14242 ApplicationErrorReport.CrashInfo crashInfo) {
14243 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
14244 UserHandle.getUserId(Binder.getCallingUid()), processName,
14245 r == null ? -1 : r.info.flags,
14246 crashInfo.exceptionClassName,
14247 crashInfo.exceptionMessage,
14248 crashInfo.throwFileName,
14249 crashInfo.throwLineNumber);
14250
14251 addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo);
14252
14253 mAppErrors.crashApplication(r, crashInfo);
14254 }

处理应用违反strict mode策略

 14256    public void handleApplicationStrictModeViolation(
14257 IBinder app,
14258 int violationMask,
14259 StrictMode.ViolationInfo info) {
14260 ProcessRecord r = findAppProcess(app, "StrictMode");
14261 if (r == null) {
14262 return;
14263 }
14264
14265 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
14266 Integer stackFingerprint = info.hashCode();
14267 boolean logIt = true;
14268 synchronized (mAlreadyLoggedViolatedStacks) {
14269 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
14270 logIt = false;
14271 // TODO: sub-sample into EventLog for these, with
14272 // the info.durationMillis? Then we'd get
14273 // the relative pain numbers, without logging all
14274 // the stack traces repeatedly. We'd want to do
14275 // likewise in the client code, which also does
14276 // dup suppression, before the Binder call.
14277 } else {
14278 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
14279 mAlreadyLoggedViolatedStacks.clear();
14280 }
14281 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
14282 }
14283 }
14284 if (logIt) {
14285 logStrictModeViolationToDropBox(r, info);
14286 }
14287 }
14288
14289 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
14290 AppErrorResult result = new AppErrorResult();
14291 synchronized (this) {
14292 final long origId = Binder.clearCallingIdentity();
14293
14294 Message msg = Message.obtain();
14295 msg.what = SHOW_STRICT_MODE_VIOLATION_UI_MSG;
14296 HashMap<String, Object> data = new HashMap<String, Object>();
14297 data.put("result", result);
14298 data.put("app", r);
14299 data.put("violationMask", violationMask);
14300 data.put("info", info);
14301 msg.obj = data;
14302 mUiHandler.sendMessage(msg);
14303
14304 Binder.restoreCallingIdentity(origId);
14305 }
14306 int res = result.get();
14307 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
14308 }
14309 }

记录违反strict mode的行为放到dropbox

 14311    // Depending on the policy in effect, there could be a bunch of
14312 // these in quick succession so we try to batch these together to
14313 // minimize disk writes, number of dropbox entries, and maximize
14314 // compression, by having more fewer, larger records.
14315 private void logStrictModeViolationToDropBox(
14316 ProcessRecord process,
14317 StrictMode.ViolationInfo info) {
14318 if (info == null) {
14319 return;
14320 }
14321 final boolean isSystemApp = process == null ||
14322 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
14323 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
14324 final String processName = process == null ? "unknown" : process.processName;
14325 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
14326 final DropBoxManager dbox = (DropBoxManager)
14327 mContext.getSystemService(Context.DROPBOX_SERVICE);
14328
14329 // Exit early if the dropbox isn't configured to accept this report type.
14330 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
14331
14332 boolean bufferWasEmpty;
14333 boolean needsFlush;
14334 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
14335 synchronized (sb) {
14336 bufferWasEmpty = sb.length() == 0;
14337 appendDropBoxProcessHeaders(process, processName, sb);
14338 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
14339 sb.append("System-App: ").append(isSystemApp).append("\n");
14340 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
14341 if (info.violationNumThisLoop != 0) {
14342 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
14343 }
14344 if (info.numAnimationsRunning != 0) {
14345 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
14346 }
14347 if (info.broadcastIntentAction != null) {
14348 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
14349 }
14350 if (info.durationMillis != -1) {
14351 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
14352 }
14353 if (info.numInstances != -1) {
14354 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
14355 }
14356 if (info.tags != null) {
14357 for (String tag : info.tags) {
14358 sb.append("Span-Tag: ").append(tag).append("\n");
14359 }
14360 }
14361 sb.append("\n");
14362 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
14363 sb.append(info.crashInfo.stackTrace);
14364 sb.append("\n");
14365 }
14366 if (info.message != null) {
14367 sb.append(info.message);
14368 sb.append("\n");
14369 }
14370
14371 // Only buffer up to ~64k. Various logging bits truncate
14372 // things at 128k.
14373 needsFlush = (sb.length() > 64 * 1024);
14374 }
14375
14376 // Flush immediately if the buffer's grown too large, or this
14377 // is a non-system app. Non-system apps are isolated with a
14378 // different tag & policy and not batched.
14379 //
14380 // Batching is useful during internal testing with
14381 // StrictMode settings turned up high. Without batching,
14382 // thousands of separate files could be created on boot.
14383 if (!isSystemApp || needsFlush) {
14384 new Thread("Error dump: " + dropboxTag) {
14385 @Override
14386 public void run() {
14387 String report;
14388 synchronized (sb) {
14389 report = sb.toString();
14390 sb.delete(0, sb.length());
14391 sb.trimToSize();
14392 }
14393 if (report.length() != 0) {
14394 dbox.addText(dropboxTag, report);
14395 }
14396 }
14397 }.start();
14398 return;
14399 }
14400
14401 // System app batching:
14402 if (!bufferWasEmpty) {
14403 // An existing dropbox-writing thread is outstanding, so
14404 // we don't need to start it up. The existing thread will
14405 // catch the buffer appends we just did.
14406 return;
14407 }
14408
14409 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
14410 // (After this point, we shouldn't access AMS internal data structures.)
14411 new Thread("Error dump: " + dropboxTag) {
14412 @Override
14413 public void run() {
14414 // 5 second sleep to let stacks arrive and be batched together
14415 try {
14416 Thread.sleep(5000); // 5 seconds
14417 } catch (InterruptedException e) {}
14418
14419 String errorReport;
14420 synchronized (mStrictModeBuffer) {
14421 errorReport = mStrictModeBuffer.toString();
14422 if (errorReport.length() == 0) {
14423 return;
14424 }
14425 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
14426 mStrictModeBuffer.trimToSize();
14427 }
14428 dbox.addText(dropboxTag, errorReport);
14429 }
14430 }.start();
14431 }

处理应用wtf

 14433    /**
14434 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
14435 * @param app object of the crashing app, null for the system server
14436 * @param tag reported by the caller
14437 * @param system whether this wtf is coming from the system
14438 * @param crashInfo describing the context of the error
14439 * @return true if the process should exit immediately (WTF is fatal)
14440 */
14441 public boolean handleApplicationWtf(final IBinder app, final String tag, boolean system,
14442 final ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
14443 final int callingUid = Binder.getCallingUid();
14444 final int callingPid = Binder.getCallingPid();
14445
14446 if (system) {
14447 // If this is coming from the system, we could very well have low-level
14448 // system locks held, so we want to do this all asynchronously. And we
14449 // never want this to become fatal, so there is that too.
14450 mHandler.post(new Runnable() {
14451 @Override public void run() {
14452 handleApplicationWtfInner(callingUid, callingPid, app, tag, crashInfo);
14453 }
14454 });
14455 return false;
14456 }
14457
14458 final ProcessRecord r = handleApplicationWtfInner(callingUid, callingPid, app, tag,
14459 crashInfo);
14460
14461 final boolean isFatal = "eng".equals(Build.TYPE) || Settings.Global
14462 .getInt(mContext.getContentResolver(), Settings.Global.WTF_IS_FATAL, 0) != 0;
14463 final boolean isSystem = (r == null) || r.persistent;
14464
14465 if (isFatal && !isSystem) {
14466 mAppErrors.crashApplication(r, crashInfo);
14467 return true;
14468 } else {
14469 return false;
14470 }
14471 }
14472
14473 ProcessRecord handleApplicationWtfInner(int callingUid, int callingPid, IBinder app, String tag,
14474 final ApplicationErrorReport.CrashInfo crashInfo) {
14475 final ProcessRecord r = findAppProcess(app, "WTF");
14476 final String processName = app == null ? "system_server"
14477 : (r == null ? "unknown" : r.processName);
14478
14479 EventLog.writeEvent(EventLogTags.AM_WTF, UserHandle.getUserId(callingUid), callingPid,
14480 processName, r == null ? -1 : r.info.flags, tag, crashInfo.exceptionMessage);
14481
14482 addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
14483
14484 return r;
14485 }

找到应用的process

 14486
14487 /**
14488 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
14489 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
14490 */
14491 private ProcessRecord findAppProcess(IBinder app, String reason) {
14492 if (app == null) {
14493 return null;
14494 }
14495
14496 synchronized (this) {
14497 final int NP = mProcessNames.getMap().size();
14498 for (int ip=0; ip<NP; ip++) {
14499 SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
14500 final int NA = apps.size();
14501 for (int ia=0; ia<NA; ia++) {
14502 ProcessRecord p = apps.valueAt(ia);
14503 if (p.thread != null && p.thread.asBinder() == app) {
14504 return p;
14505 }
14506 }
14507 }
14508
14509 Slog.w(TAG, "Can't find mystery application for " + reason
14510 + " from pid=" + Binder.getCallingPid()
14511 + " uid=" + Binder.getCallingUid() + ": " + app);
14512 return null;
14513 }
14514 }

添加dropbox里进程头

 14516    /**
14517 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
14518 * to append various headers to the dropbox log text.
14519 */
14520 private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
14521 StringBuilder sb) {
14522 // Watchdog thread ends up invoking this function (with
14523 // a null ProcessRecord) to add the stack file to dropbox.
14524 // Do not acquire a lock on this (am) in such cases, as it
14525 // could cause a potential deadlock, if and when watchdog
14526 // is invoked due to unavailability of lock on am and it
14527 // would prevent watchdog from killing system_server.
14528 if (process == null) {
14529 sb.append("Process: ").append(processName).append("\n");
14530 return;
14531 }
14532 // Note: ProcessRecord 'process' is guarded by the service
14533 // instance. (notably process.pkgList, which could otherwise change
14534 // concurrently during execution of this method)
14535 synchronized (this) {
14536 sb.append("Process: ").append(processName).append("\n");
14537 sb.append("PID: ").append(process.pid).append("\n");
14538 int flags = process.info.flags;
14539 IPackageManager pm = AppGlobals.getPackageManager();
14540 sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
14541 for (int ip=0; ip<process.pkgList.size(); ip++) {
14542 String pkg = process.pkgList.keyAt(ip);
14543 sb.append("Package: ").append(pkg);
14544 try {
14545 PackageInfo pi = pm.getPackageInfo(pkg, 0, UserHandle.getCallingUserId());
14546 if (pi != null) {
14547 sb.append(" v").append(pi.versionCode);
14548 if (pi.versionName != null) {
14549 sb.append(" (").append(pi.versionName).append(")");
14550 }
14551 }
14552 } catch (RemoteException e) {
14553 Slog.e(TAG, "Error getting package info: " + pkg, e);
14554 }
14555 sb.append("\n");
14556 }
14557 }
14558 }

进程的类别

 14560    private static String processClass(ProcessRecord process) {
14561 if (process == null || process.pid == MY_PID) {
14562 return "system_server";
14563 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
14564 return "system_app";
14565 } else {
14566 return "data_app";
14567 }
14568 }

wtf的start和count

 14570    private volatile long mWtfClusterStart;
14571 private volatile int mWtfClusterCount;

添加错误到dropbox

 14573    /**
14574 * Write a description of an error (crash, WTF, ANR) to the drop box.
14575 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
14576 * @param process which caused the error, null means the system server
14577 * @param activity which triggered the error, null if unknown
14578 * @param parent activity related to the error, null if unknown
14579 * @param subject line related to the error, null if absent
14580 * @param report in long form describing the error, null if absent
14581 * @param dataFile text file to include in the report, null if none
14582 * @param crashInfo giving an application stack trace, null if absent
14583 */
14584 public void addErrorToDropBox(String eventType,
14585 ProcessRecord process, String processName, ActivityRecord activity,
14586 ActivityRecord parent, String subject,
14587 final String report, final File dataFile,
14588 final ApplicationErrorReport.CrashInfo crashInfo) {
14589 // NOTE -- this must never acquire the ActivityManagerService lock,
14590 // otherwise the watchdog may be prevented from resetting the system.
14591
14592 // Bail early if not published yet
14593 if (ServiceManager.getService(Context.DROPBOX_SERVICE) == null) return;
14594 final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class);
14595
14596 // Exit early if the dropbox isn't configured to accept this report type.
14597 final String dropboxTag = processClass(process) + "_" + eventType;
14598 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
14599
14600 // Rate-limit how often we're willing to do the heavy lifting below to
14601 // collect and record logs; currently 5 logs per 10 second period.
14602 final long now = SystemClock.elapsedRealtime();
14603 if (now - mWtfClusterStart > 10 * DateUtils.SECOND_IN_MILLIS) {
14604 mWtfClusterStart = now;
14605 mWtfClusterCount = 1;
14606 } else {
14607 if (mWtfClusterCount++ >= 5) return;
14608 }
14609
14610 final StringBuilder sb = new StringBuilder(1024);
14611 appendDropBoxProcessHeaders(process, processName, sb);
14612 if (process != null) {
14613 sb.append("Foreground: ")
14614 .append(process.isInterestingToUserLocked() ? "Yes" : "No")
14615 .append("\n");
14616 }
14617 if (activity != null) {
14618 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
14619 }
14620 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
14621 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
14622 }
14623 if (parent != null && parent != activity) {
14624 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
14625 }
14626 if (subject != null) {
14627 sb.append("Subject: ").append(subject).append("\n");
14628 }
14629 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
14630 if (Debug.isDebuggerConnected()) {
14631 sb.append("Debugger: Connected\n");
14632 }
14633 sb.append("\n");
14634
14635 // Do the rest in a worker thread to avoid blocking the caller on I/O
14636 // (After this point, we shouldn't access AMS internal data structures.)
14637 Thread worker = new Thread("Error dump: " + dropboxTag) {
14638 @Override
14639 public void run() {
14640 if (report != null) {
14641 sb.append(report);
14642 }
14643
14644 String setting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
14645 int lines = Settings.Global.getInt(mContext.getContentResolver(), setting, 0);
14646 int maxDataFileSize = DROPBOX_MAX_SIZE - sb.length()
14647 - lines * RESERVED_BYTES_PER_LOGCAT_LINE;
14648
14649 if (dataFile != null && maxDataFileSize > 0) {
14650 try {
14651 sb.append(FileUtils.readTextFile(dataFile, maxDataFileSize,
14652 "\n\n[[TRUNCATED]]"));
14653 } catch (IOException e) {
14654 Slog.e(TAG, "Error reading " + dataFile, e);
14655 }
14656 }
14657 if (crashInfo != null && crashInfo.stackTrace != null) {
14658 sb.append(crashInfo.stackTrace);
14659 }
14660
14661 if (lines > 0) {
14662 sb.append("\n");
14663
14664 // Merge several logcat streams, and take the last N lines
14665 InputStreamReader input = null;
14666 try {
14667 java.lang.Process logcat = new ProcessBuilder(
14668 "/system/bin/timeout", "-k", "15s", "10s",
14669 "/system/bin/logcat", "-v", "threadtime", "-b", "events", "-b", "system",
14670 "-b", "main", "-b", "crash", "-t", String.valueOf(lines))
14671 .redirectErrorStream(true).start();
14672
14673 try { logcat.getOutputStream().close(); } catch (IOException e) {}
14674 try { logcat.getErrorStream().close(); } catch (IOException e) {}
14675 input = new InputStreamReader(logcat.getInputStream());
14676
14677 int num;
14678 char[] buf = new char[8192];
14679 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
14680 } catch (IOException e) {
14681 Slog.e(TAG, "Error running logcat", e);
14682 } finally {
14683 if (input != null) try { input.close(); } catch (IOException e) {}
14684 }
14685 }
14686
14687 dbox.addText(dropboxTag, sb.toString());
14688 }
14689 };
14690
14691 if (process == null) {
14692 // If process is null, we are being called from some internal code
14693 // and may be about to die -- run this synchronously.
14694 worker.run();
14695 } else {
14696 worker.start();
14697 }
14698 }

在错误状态下获取进程信息

 14700    @Override
14701 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
14702 enforceNotIsolatedCaller("getProcessesInErrorState");
14703 // assume our apps are happy - lazy create the list
14704 List<ActivityManager.ProcessErrorStateInfo> errList = null;
14705
14706 final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
14707 Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
14708 int userId = UserHandle.getUserId(Binder.getCallingUid());
14709
14710 synchronized (this) {
14711
14712 // iterate across all processes
14713 for (int i=mLruProcesses.size()-1; i>=0; i--) {
14714 ProcessRecord app = mLruProcesses.get(i);
14715 if (!allUsers && app.userId != userId) {
14716 continue;
14717 }
14718 if ((app.thread != null) && (app.crashing || app.notResponding)) {
14719 // This one's in trouble, so we'll generate a report for it
14720 // crashes are higher priority (in case there's a crash *and* an anr)
14721 ActivityManager.ProcessErrorStateInfo report = null;
14722 if (app.crashing) {
14723 report = app.crashingReport;
14724 } else if (app.notResponding) {
14725 report = app.notRespondingReport;
14726 }
14727
14728 if (report != null) {
14729 if (errList == null) {
14730 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
14731 }
14732 errList.add(report);
14733 } else {
14734 Slog.w(TAG, "Missing app error report, app = " + app.processName +
14735 " crashing = " + app.crashing +
14736 " notResponding = " + app.notResponding);
14737 }
14738 }
14739 }
14740 }
14741
14742 return errList;
14743 }

进程状态的重要值

 14745    static int procStateToImportance(int procState, int memAdj,
14746 ActivityManager.RunningAppProcessInfo currApp,
14747 int clientTargetSdk) {
14748 int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk(
14749 procState, clientTargetSdk);
14750 if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
14751 currApp.lru = memAdj;
14752 } else {
14753 currApp.lru = 0;
14754 }
14755 return imp;
14756 }

填写进程内存info

 14758    private void fillInProcMemInfo(ProcessRecord app,
14759 ActivityManager.RunningAppProcessInfo outInfo,
14760 int clientTargetSdk) {
14761 outInfo.pid = app.pid;
14762 outInfo.uid = app.info.uid;
14763 if (mHeavyWeightProcess == app) {
14764 outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
14765 }
14766 if (app.persistent) {
14767 outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
14768 }
14769 if (app.activities.size() > 0) {
14770 outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
14771 }
14772 outInfo.lastTrimLevel = app.trimMemoryLevel;
14773 int adj = app.curAdj;
14774 int procState = app.curProcState;
14775 outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk);
14776 outInfo.importanceReasonCode = app.adjTypeCode;
14777 outInfo.processState = app.curProcState;
14778 }

获取运行进程信息,运行外部程序,system_server的内存状态与trim内存状态

 14780    @Override
14781 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
14782 enforceNotIsolatedCaller("getRunningAppProcesses");
14783
14784 final int callingUid = Binder.getCallingUid();
14785 final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
14786
14787 // Lazy instantiation of list
14788 List<ActivityManager.RunningAppProcessInfo> runList = null;
14789 final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
14790 callingUid) == PackageManager.PERMISSION_GRANTED;
14791 final int userId = UserHandle.getUserId(callingUid);
14792 final boolean allUids = isGetTasksAllowed(
14793 "getRunningAppProcesses", Binder.getCallingPid(), callingUid);
14794
14795 synchronized (this) {
14796 // Iterate across all processes
14797 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
14798 ProcessRecord app = mLruProcesses.get(i);
14799 if ((!allUsers && app.userId != userId)
14800 || (!allUids && app.uid != callingUid)) {
14801 continue;
14802 }
14803 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
14804 // Generate process state info for running application
14805 ActivityManager.RunningAppProcessInfo currApp =
14806 new ActivityManager.RunningAppProcessInfo(app.processName,
14807 app.pid, app.getPackageList());
14808 fillInProcMemInfo(app, currApp, clientTargetSdk);
14809 if (app.adjSource instanceof ProcessRecord) {
14810 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
14811 currApp.importanceReasonImportance =
14812 ActivityManager.RunningAppProcessInfo.procStateToImportance(
14813 app.adjSourceProcState);
14814 } else if (app.adjSource instanceof ActivityRecord) {
14815 ActivityRecord r = (ActivityRecord)app.adjSource;
14816 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
14817 }
14818 if (app.adjTarget instanceof ComponentName) {
14819 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
14820 }
14821 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
14822 // + " lru=" + currApp.lru);
14823 if (runList == null) {
14824 runList = new ArrayList<>();
14825 }
14826 runList.add(currApp);
14827 }
14828 }
14829 }
14830 return runList;
14831 }
14832
14833 @Override
14834 public List<ApplicationInfo> getRunningExternalApplications() {
14835 enforceNotIsolatedCaller("getRunningExternalApplications");
14836 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
14837 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
14838 if (runningApps != null && runningApps.size() > 0) {
14839 Set<String> extList = new HashSet<String>();
14840 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
14841 if (app.pkgList != null) {
14842 for (String pkg : app.pkgList) {
14843 extList.add(pkg);
14844 }
14845 }
14846 }
14847 IPackageManager pm = AppGlobals.getPackageManager();
14848 for (String pkg : extList) {
14849 try {
14850 ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserHandle.getCallingUserId());
14851 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
14852 retList.add(info);
14853 }
14854 } catch (RemoteException e) {
14855 }
14856 }
14857 }
14858 return retList;
14859 }
14860
14861 @Override
14862 public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) {
14863 enforceNotIsolatedCaller("getMyMemoryState");
14864
14865 final int callingUid = Binder.getCallingUid();
14866 final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
14867
14868 synchronized (this) {
14869 ProcessRecord proc;
14870 synchronized (mPidsSelfLocked) {
14871 proc = mPidsSelfLocked.get(Binder.getCallingPid());
14872 }
14873 fillInProcMemInfo(proc, outInfo, clientTargetSdk);
14874 }
14875 }
14876
14877 @Override
14878 public int getMemoryTrimLevel() {
14879 enforceNotIsolatedCaller("getMyMemoryState");
14880 synchronized (this) {
14881 return mLastMemoryLevel;
14882 }
14883 }

shell command回调

 14885    @Override
14886 public void onShellCommand(FileDescriptor in, FileDescriptor out,
14887 FileDescriptor err, String[] args, ShellCallback callback,
14888 ResultReceiver resultReceiver) {
14889 (new ActivityManagerShellCommand(this, false)).exec(
14890 this, in, out, err, args, callback, resultReceiver);
14891 }
14892

dump

 14893    @Override
14894 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
14895 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
14896
14897 boolean dumpAll = false;
14898 boolean dumpClient = false;
14899 boolean dumpCheckin = false;
14900 boolean dumpCheckinFormat = false;
14901 boolean dumpVisibleStacksOnly = false;
14902 boolean dumpFocusedStackOnly = false;
14903 String dumpPackage = null;
14904
14905 int opti = 0;
14906 while (opti < args.length) {
14907 String opt = args[opti];
14908 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
14909 break;
14910 }
14911 opti++;
14912 if ("-a".equals(opt)) {
14913 dumpAll = true;
14914 } else if ("-c".equals(opt)) {
14915 dumpClient = true;
14916 } else if ("-v".equals(opt)) {
14917 dumpVisibleStacksOnly = true;
14918 } else if ("-f".equals(opt)) {
14919 dumpFocusedStackOnly = true;
14920 } else if ("-p".equals(opt)) {
14921 if (opti < args.length) {
14922 dumpPackage = args[opti];
14923 opti++;
14924 } else {
14925 pw.println("Error: -p option requires package argument");
14926 return;
14927 }
14928 dumpClient = true;
14929 } else if ("--checkin".equals(opt)) {
14930 dumpCheckin = dumpCheckinFormat = true;
14931 } else if ("-C".equals(opt)) {
14932 dumpCheckinFormat = true;
14933 } else if ("-h".equals(opt)) {
14934 ActivityManagerShellCommand.dumpHelp(pw, true);
14935 return;
14936 } else {
14937 pw.println("Unknown argument: " + opt + "; use -h for help");
14938 }
14939 }
14940
14941 long origId = Binder.clearCallingIdentity();
14942 boolean more = false;
14943 // Is the caller requesting to dump a particular piece of data?
14944 if (opti < args.length) {
14945 String cmd = args[opti];
14946 opti++;
14947 if ("activities".equals(cmd) || "a".equals(cmd)) {
14948 synchronized (this) {
14949 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
14950 }
14951 } else if ("lastanr".equals(cmd)) {
14952 synchronized (this) {
14953 dumpLastANRLocked(pw);
14954 }
14955 } else if ("starter".equals(cmd)) {
14956 synchronized (this) {
14957 dumpActivityStarterLocked(pw);
14958 }
14959 } else if ("recents".equals(cmd) || "r".equals(cmd)) {
14960 synchronized (this) {
14961 dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage);
14962 }
14963 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
14964 String[] newArgs;
14965 String name;
14966 if (opti >= args.length) {
14967 name = null;
14968 newArgs = EMPTY_STRING_ARRAY;
14969 } else {
14970 dumpPackage = args[opti];
14971 opti++;
14972 newArgs = new String[args.length - opti];
14973 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
14974 args.length - opti);
14975 }
14976 synchronized (this) {
14977 dumpBroadcastsLocked(fd, pw, args, opti, true, dumpPackage);
14978 }
14979 } else if ("broadcast-stats".equals(cmd)) {
14980 String[] newArgs;
14981 String name;
14982 if (opti >= args.length) {
14983 name = null;
14984 newArgs = EMPTY_STRING_ARRAY;
14985 } else {
14986 dumpPackage = args[opti];
14987 opti++;
14988 newArgs = new String[args.length - opti];
14989 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
14990 args.length - opti);
14991 }
14992 synchronized (this) {
14993 if (dumpCheckinFormat) {
14994 dumpBroadcastStatsCheckinLocked(fd, pw, args, opti, dumpCheckin,
14995 dumpPackage);
14996 } else {
14997 dumpBroadcastStatsLocked(fd, pw, args, opti, true, dumpPackage);
14998 }
14999 }
15000 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
15001 String[] newArgs;
15002 String name;
15003 if (opti >= args.length) {
15004 name = null;
15005 newArgs = EMPTY_STRING_ARRAY;
15006 } else {
15007 dumpPackage = args[opti];
15008 opti++;
15009 newArgs = new String[args.length - opti];
15010 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
15011 args.length - opti);
15012 }
15013 synchronized (this) {
15014 dumpPendingIntentsLocked(fd, pw, args, opti, true, dumpPackage);
15015 }
15016 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
15017 String[] newArgs;
15018 String name;
15019 if (opti >= args.length) {
15020 name = null;
15021 newArgs = EMPTY_STRING_ARRAY;
15022 } else {
15023 dumpPackage = args[opti];
15024 opti++;
15025 newArgs = new String[args.length - opti];
15026 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
15027 args.length - opti);
15028 }
15029 synchronized (this) {
15030 dumpProcessesLocked(fd, pw, args, opti, true, dumpPackage);
15031 }
15032 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
15033 synchronized (this) {
15034 dumpOomLocked(fd, pw, args, opti, true);
15035 }
15036 } else if ("permissions".equals(cmd) || "perm".equals(cmd)) {
15037 synchronized (this) {
15038 dumpPermissionsLocked(fd, pw, args, opti, true, null);
15039 }
15040 } else if ("provider".equals(cmd)) {
15041 String[] newArgs;
15042 String name;
15043 if (opti >= args.length) {
15044 name = null;
15045 newArgs = EMPTY_STRING_ARRAY;
15046 } else {
15047 name = args[opti];
15048 opti++;
15049 newArgs = new String[args.length - opti];
15050 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
15051 }
15052 if (!dumpProvider(fd, pw, name, newArgs, 0, dumpAll)) {
15053 pw.println("No providers match: " + name);
15054 pw.println("Use -h for help.");
15055 }
15056 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
15057 synchronized (this) {
15058 dumpProvidersLocked(fd, pw, args, opti, true, null);
15059 }
15060 } else if ("service".equals(cmd)) {
15061 String[] newArgs;
15062 String name;
15063 if (opti >= args.length) {
15064 name = null;
15065 newArgs = EMPTY_STRING_ARRAY;
15066 } else {
15067 name = args[opti];
15068 opti++;
15069 newArgs = new String[args.length - opti];
15070 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
15071 args.length - opti);
15072 }
15073 if (!mServices.dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
15074 pw.println("No services match: " + name);
15075 pw.println("Use -h for help.");
15076 }
15077 } else if ("package".equals(cmd)) {
15078 String[] newArgs;
15079 if (opti >= args.length) {
15080 pw.println("package: no package name specified");
15081 pw.println("Use -h for help.");
15082 } else {
15083 dumpPackage = args[opti];
15084 opti++;
15085 newArgs = new String[args.length - opti];
15086 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
15087 args.length - opti);
15088 args = newArgs;
15089 opti = 0;
15090 more = true;
15091 }
15092 } else if ("associations".equals(cmd) || "as".equals(cmd)) {
15093 synchronized (this) {
15094 dumpAssociationsLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
15095 }
15096 } else if ("settings".equals(cmd)) {
15097 synchronized (this) {
15098 mConstants.dump(pw);
15099 }
15100 } else if ("services".equals(cmd) || "s".equals(cmd)) {
15101 if (dumpClient) {
15102 ActiveServices.ServiceDumper dumper;
15103 synchronized (this) {
15104 dumper = mServices.newServiceDumperLocked(fd, pw, args, opti, true,
15105 dumpPackage);
15106 }
15107 dumper.dumpWithClient();
15108 } else {
15109 synchronized (this) {
15110 mServices.newServiceDumperLocked(fd, pw, args, opti, true,
15111 dumpPackage).dumpLocked();
15112 }
15113 }
15114 } else if ("locks".equals(cmd)) {
15115 LockGuard.dump(fd, pw, args);
15116 } else {
15117 // Dumping a single activity?
15118 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll, dumpVisibleStacksOnly,
15119 dumpFocusedStackOnly)) {
15120 ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
15121 int res = shell.exec(this, null, fd, null, args, null,
15122 new ResultReceiver(null));
15123 if (res < 0) {
15124 pw.println("Bad activity command, or no activities match: " + cmd);
15125 pw.println("Use -h for help.");
15126 }
15127 }
15128 }
15129 if (!more) {
15130 Binder.restoreCallingIdentity(origId);
15131 return;
15132 }
15133 }
15134
15135 // No piece of data specified, dump everything.
15136 if (dumpCheckinFormat) {
15137 dumpBroadcastStatsCheckinLocked(fd, pw, args, opti, dumpCheckin, dumpPackage);
15138 } else if (dumpClient) {
15139 ActiveServices.ServiceDumper sdumper;
15140 synchronized (this) {
15141 mConstants.dump(pw);
15142 pw.println();
15143 if (dumpAll) {
15144 pw.println("-------------------------------------------------------------------------------");
15145 }
15146 dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15147 pw.println();
15148 if (dumpAll) {
15149 pw.println("-------------------------------------------------------------------------------");
15150 }
15151 dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15152 pw.println();
15153 if (dumpAll) {
15154 pw.println("-------------------------------------------------------------------------------");
15155 }
15156 if (dumpAll || dumpPackage != null) {
15157 dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15158 pw.println();
15159 if (dumpAll) {
15160 pw.println("-------------------------------------------------------------------------------");
15161 }
15162 }
15163 dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15164 pw.println();
15165 if (dumpAll) {
15166 pw.println("-------------------------------------------------------------------------------");
15167 }
15168 dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15169 pw.println();
15170 if (dumpAll) {
15171 pw.println("-------------------------------------------------------------------------------");
15172 }
15173 sdumper = mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll,
15174 dumpPackage);
15175 }
15176 sdumper.dumpWithClient();
15177 pw.println();
15178 synchronized (this) {
15179 if (dumpAll) {
15180 pw.println("-------------------------------------------------------------------------------");
15181 }
15182 dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15183 pw.println();
15184 if (dumpAll) {
15185 pw.println("-------------------------------------------------------------------------------");
15186 }
15187 dumpLastANRLocked(pw);
15188 pw.println();
15189 if (dumpAll) {
15190 pw.println("-------------------------------------------------------------------------------");
15191 }
15192 dumpActivityStarterLocked(pw);
15193 pw.println();
15194 if (dumpAll) {
15195 pw.println("-------------------------------------------------------------------------------");
15196 }
15197 dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
15198 if (mAssociations.size() > 0) {
15199 pw.println();
15200 if (dumpAll) {
15201 pw.println("-------------------------------------------------------------------------------");
15202 }
15203 dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
15204 }
15205 pw.println();
15206 if (dumpAll) {
15207 pw.println("-------------------------------------------------------------------------------");
15208 }
15209 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15210 }
15211
15212 } else {
15213 synchronized (this) {
15214 mConstants.dump(pw);
15215 pw.println();
15216 if (dumpAll) {
15217 pw.println("-------------------------------------------------------------------------------");
15218 }
15219 dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15220 pw.println();
15221 if (dumpAll) {
15222 pw.println("-------------------------------------------------------------------------------");
15223 }
15224 dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15225 pw.println();
15226 if (dumpAll) {
15227 pw.println("-------------------------------------------------------------------------------");
15228 }
15229 if (dumpAll || dumpPackage != null) {
15230 dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15231 pw.println();
15232 if (dumpAll) {
15233 pw.println("-------------------------------------------------------------------------------");
15234 }
15235 }
15236 dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15237 pw.println();
15238 if (dumpAll) {
15239 pw.println("-------------------------------------------------------------------------------");
15240 }
15241 dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15242 pw.println();
15243 if (dumpAll) {
15244 pw.println("-------------------------------------------------------------------------------");
15245 }
15246 mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll, dumpPackage)
15247 .dumpLocked();
15248 pw.println();
15249 if (dumpAll) {
15250 pw.println("-------------------------------------------------------------------------------");
15251 }
15252 dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15253 pw.println();
15254 if (dumpAll) {
15255 pw.println("-------------------------------------------------------------------------------");
15256 }
15257 dumpLastANRLocked(pw);
15258 pw.println();
15259 if (dumpAll) {
15260 pw.println("-------------------------------------------------------------------------------");
15261 }
15262 dumpActivityStarterLocked(pw);
15263 pw.println();
15264 if (dumpAll) {
15265 pw.println("-------------------------------------------------------------------------------");
15266 }
15267 dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
15268 if (mAssociations.size() > 0) {
15269 pw.println();
15270 if (dumpAll) {
15271 pw.println("-------------------------------------------------------------------------------");
15272 }
15273 dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
15274 }
15275 pw.println();
15276 if (dumpAll) {
15277 pw.println("-------------------------------------------------------------------------------");
15278 }
15279 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
15280 }
15281 }
15282 Binder.restoreCallingIdentity(origId);
15283 }
15284
15285 private void dumpLastANRLocked(PrintWriter pw) {
15286 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)");
15287 if (mLastANRState == null) {
15288 pw.println(" <no ANR has occurred since boot>");
15289 } else {
15290 pw.println(mLastANRState);
15291 }
15292 }
15293
15294 private void dumpActivityStarterLocked(PrintWriter pw) {
15295 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity starter)");
15296 mActivityStarter.dump(pw, "");
15297 }
15298
15299 void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15300 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
15301 dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage,
15302 "ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
15303 }
15304
15305 void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15306 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) {
15307 pw.println(header);
15308
15309 boolean printedAnything = mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient,
15310 dumpPackage);
15311 boolean needSep = printedAnything;
15312
15313 boolean printed = ActivityStackSupervisor.printThisActivity(pw,
15314 mStackSupervisor.getResumedActivityLocked(),
15315 dumpPackage, needSep, " ResumedActivity: ");
15316 if (printed) {
15317 printedAnything = true;
15318 needSep = false;
15319 }
15320
15321 if (dumpPackage == null) {
15322 if (needSep) {
15323 pw.println();
15324 }
15325 printedAnything = true;
15326 mStackSupervisor.dump(pw, " ");
15327 }
15328
15329 if (!printedAnything) {
15330 pw.println(" (nothing)");
15331 }
15332 }
15333
15334 void dumpRecentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15335 int opti, boolean dumpAll, String dumpPackage) {
15336 pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
15337
15338 boolean printedAnything = false;
15339
15340 if (mRecentTasks != null && mRecentTasks.size() > 0) {
15341 boolean printedHeader = false;
15342
15343 final int N = mRecentTasks.size();
15344 for (int i=0; i<N; i++) {
15345 TaskRecord tr = mRecentTasks.get(i);
15346 if (dumpPackage != null) {
15347 if (tr.realActivity == null ||
15348 !dumpPackage.equals(tr.realActivity.getPackageName())) {
15349 continue;
15350 }
15351 }
15352 if (!printedHeader) {
15353 pw.println(" Recent tasks:");
15354 printedHeader = true;
15355 printedAnything = true;
15356 }
15357 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
15358 pw.println(tr);
15359 if (dumpAll) {
15360 mRecentTasks.get(i).dump(pw, " ");
15361 }
15362 }
15363 }
15364
15365 if (!printedAnything) {
15366 pw.println(" (nothing)");
15367 }
15368 }
15369
15370 void dumpAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15371 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
15372 pw.println("ACTIVITY MANAGER ASSOCIATIONS (dumpsys activity associations)");
15373
15374 int dumpUid = 0;
15375 if (dumpPackage != null) {
15376 IPackageManager pm = AppGlobals.getPackageManager();
15377 try {
15378 dumpUid = pm.getPackageUid(dumpPackage, MATCH_ANY_USER, 0);
15379 } catch (RemoteException e) {
15380 }
15381 }
15382
15383 boolean printedAnything = false;
15384
15385 final long now = SystemClock.uptimeMillis();
15386
15387 for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) {
15388 ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents
15389 = mAssociations.valueAt(i1);
15390 for (int i2=0, N2=targetComponents.size(); i2<N2; i2++) {
15391 SparseArray<ArrayMap<String, Association>> sourceUids
15392 = targetComponents.valueAt(i2);
15393 for (int i3=0, N3=sourceUids.size(); i3<N3; i3++) {
15394 ArrayMap<String, Association> sourceProcesses = sourceUids.valueAt(i3);
15395 for (int i4=0, N4=sourceProcesses.size(); i4<N4; i4++) {
15396 Association ass = sourceProcesses.valueAt(i4);
15397 if (dumpPackage != null) {
15398 if (!ass.mTargetComponent.getPackageName().equals(dumpPackage)
15399 && UserHandle.getAppId(ass.mSourceUid) != dumpUid) {
15400 continue;
15401 }
15402 }
15403 printedAnything = true;
15404 pw.print(" ");
15405 pw.print(ass.mTargetProcess);
15406 pw.print("/");
15407 UserHandle.formatUid(pw, ass.mTargetUid);
15408 pw.print(" <- ");
15409 pw.print(ass.mSourceProcess);
15410 pw.print("/");
15411 UserHandle.formatUid(pw, ass.mSourceUid);
15412 pw.println();
15413 pw.print(" via ");
15414 pw.print(ass.mTargetComponent.flattenToShortString());
15415 pw.println();
15416 pw.print(" ");
15417 long dur = ass.mTime;
15418 if (ass.mNesting > 0) {
15419 dur += now - ass.mStartTime;
15420 }
15421 TimeUtils.formatDuration(dur, pw);
15422 pw.print(" (");
15423 pw.print(ass.mCount);
15424 pw.print(" times)");
15425 pw.print(" ");
15426 for (int i=0; i<ass.mStateTimes.length; i++) {
15427 long amt = ass.mStateTimes[i];
15428 if ((ass.mLastState-ActivityManager.MIN_PROCESS_STATE) == i) {
15429 amt += now - ass.mLastStateUptime;
15430 }
15431 if (amt != 0) {
15432 pw.print(" ");
15433 pw.print(ProcessList.makeProcStateString(
15434 i + ActivityManager.MIN_PROCESS_STATE));
15435 pw.print("=");
15436 TimeUtils.formatDuration(amt, pw);
15437 if ((ass.mLastState-ActivityManager.MIN_PROCESS_STATE) == i) {
15438 pw.print("*");
15439 }
15440 }
15441 }
15442 pw.println();
15443 if (ass.mNesting > 0) {
15444 pw.print(" Currently active: ");
15445 TimeUtils.formatDuration(now - ass.mStartTime, pw);
15446 pw.println();
15447 }
15448 }
15449 }
15450 }
15451
15452 }
15453
15454 if (!printedAnything) {
15455 pw.println(" (nothing)");
15456 }
15457 }
15458
15459 boolean dumpUids(PrintWriter pw, String dumpPackage, SparseArray<UidRecord> uids,
15460 String header, boolean needSep) {
15461 boolean printed = false;
15462 int whichAppId = -1;
15463 if (dumpPackage != null) {
15464 try {
15465 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
15466 dumpPackage, 0);
15467 whichAppId = UserHandle.getAppId(info.uid);
15468 } catch (NameNotFoundException e) {
15469 e.printStackTrace();
15470 }
15471 }
15472 for (int i=0; i<uids.size(); i++) {
15473 UidRecord uidRec = uids.valueAt(i);
15474 if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) {
15475 continue;
15476 }
15477 if (!printed) {
15478 printed = true;
15479 if (needSep) {
15480 pw.println();
15481 }
15482 pw.print(" ");
15483 pw.println(header);
15484 needSep = true;
15485 }
15486 pw.print(" UID "); UserHandle.formatUid(pw, uidRec.uid);
15487 pw.print(": "); pw.println(uidRec);
15488 }
15489 return printed;
15490 }
15491
15492 void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15493 int opti, boolean dumpAll, String dumpPackage) {
15494 boolean needSep = false;
15495 boolean printedAnything = false;
15496 int numPers = 0;
15497
15498 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
15499
15500 if (dumpAll) {
15501 final int NP = mProcessNames.getMap().size();
15502 for (int ip=0; ip<NP; ip++) {
15503 SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
15504 final int NA = procs.size();
15505 for (int ia=0; ia<NA; ia++) {
15506 ProcessRecord r = procs.valueAt(ia);
15507 if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
15508 continue;
15509 }
15510 if (!needSep) {
15511 pw.println(" All known processes:");
15512 needSep = true;
15513 printedAnything = true;
15514 }
15515 pw.print(r.persistent ? " *PERS*" : " *APP*");
15516 pw.print(" UID "); pw.print(procs.keyAt(ia));
15517 pw.print(" "); pw.println(r);
15518 r.dump(pw, " ");
15519 if (r.persistent) {
15520 numPers++;
15521 }
15522 }
15523 }
15524 }
15525
15526 if (mIsolatedProcesses.size() > 0) {
15527 boolean printed = false;
15528 for (int i=0; i<mIsolatedProcesses.size(); i++) {
15529 ProcessRecord r = mIsolatedProcesses.valueAt(i);
15530 if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
15531 continue;
15532 }
15533 if (!printed) {
15534 if (needSep) {
15535 pw.println();
15536 }
15537 pw.println(" Isolated process list (sorted by uid):");
15538 printedAnything = true;
15539 printed = true;
15540 needSep = true;
15541 }
15542 pw.print(" Isolated #"); pw.print(i); pw.print(": ");
15543 pw.println(r);
15544 }
15545 }
15546
15547 if (mActiveInstrumentation.size() > 0) {
15548 boolean printed = false;
15549 for (int i=0; i<mActiveInstrumentation.size(); i++) {
15550 ActiveInstrumentation ai = mActiveInstrumentation.get(i);
15551 if (dumpPackage != null && !ai.mClass.getPackageName().equals(dumpPackage)
15552 && !ai.mTargetInfo.packageName.equals(dumpPackage)) {
15553 continue;
15554 }
15555 if (!printed) {
15556 if (needSep) {
15557 pw.println();
15558 }
15559 pw.println(" Active instrumentation:");
15560 printedAnything = true;
15561 printed = true;
15562 needSep = true;
15563 }
15564 pw.print(" Instrumentation #"); pw.print(i); pw.print(": ");
15565 pw.println(ai);
15566 ai.dump(pw, " ");
15567 }
15568 }
15569
15570 if (mActiveUids.size() > 0) {
15571 if (dumpUids(pw, dumpPackage, mActiveUids, "UID states:", needSep)) {
15572 printedAnything = needSep = true;
15573 }
15574 }
15575 if (dumpAll) {
15576 if (mValidateUids.size() > 0) {
15577 if (dumpUids(pw, dumpPackage, mValidateUids, "UID validation:", needSep)) {
15578 printedAnything = needSep = true;
15579 }
15580 }
15581 }
15582
15583 if (mLruProcesses.size() > 0) {
15584 if (needSep) {
15585 pw.println();
15586 }
15587 pw.print(" Process LRU list (sorted by oom_adj, "); pw.print(mLruProcesses.size());
15588 pw.print(" total, non-act at ");
15589 pw.print(mLruProcesses.size()-mLruProcessActivityStart);
15590 pw.print(", non-svc at ");
15591 pw.print(mLruProcesses.size()-mLruProcessServiceStart);
15592 pw.println("):");
15593 dumpProcessOomList(pw, this, mLruProcesses, " ", "Proc", "PERS", false, dumpPackage);
15594 needSep = true;
15595 printedAnything = true;
15596 }
15597
15598 if (dumpAll || dumpPackage != null) {
15599 synchronized (mPidsSelfLocked) {
15600 boolean printed = false;
15601 for (int i=0; i<mPidsSelfLocked.size(); i++) {
15602 ProcessRecord r = mPidsSelfLocked.valueAt(i);
15603 if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
15604 continue;
15605 }
15606 if (!printed) {
15607 if (needSep) pw.println();
15608 needSep = true;
15609 pw.println(" PID mappings:");
15610 printed = true;
15611 printedAnything = true;
15612 }
15613 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
15614 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
15615 }
15616 }
15617 }
15618
15619 if (mImportantProcesses.size() > 0) {
15620 synchronized (mPidsSelfLocked) {
15621 boolean printed = false;
15622 for (int i = 0; i< mImportantProcesses.size(); i++) {
15623 ProcessRecord r = mPidsSelfLocked.get(
15624 mImportantProcesses.valueAt(i).pid);
15625 if (dumpPackage != null && (r == null
15626 || !r.pkgList.containsKey(dumpPackage))) {
15627 continue;
15628 }
15629 if (!printed) {
15630 if (needSep) pw.println();
15631 needSep = true;
15632 pw.println(" Foreground Processes:");
15633 printed = true;
15634 printedAnything = true;
15635 }
15636 pw.print(" PID #"); pw.print(mImportantProcesses.keyAt(i));
15637 pw.print(": "); pw.println(mImportantProcesses.valueAt(i));
15638 }
15639 }
15640 }
15641
15642 if (mPersistentStartingProcesses.size() > 0) {
15643 if (needSep) pw.println();
15644 needSep = true;
15645 printedAnything = true;
15646 pw.println(" Persisent processes that are starting:");
15647 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
15648 "Starting Norm", "Restarting PERS", dumpPackage);
15649 }
15650
15651 if (mRemovedProcesses.size() > 0) {
15652 if (needSep) pw.println();
15653 needSep = true;
15654 printedAnything = true;
15655 pw.println(" Processes that are being removed:");
15656 dumpProcessList(pw, this, mRemovedProcesses, " ",
15657 "Removed Norm", "Removed PERS", dumpPackage);
15658 }
15659
15660 if (mProcessesOnHold.size() > 0) {
15661 if (needSep) pw.println();
15662 needSep = true;
15663 printedAnything = true;
15664 pw.println(" Processes that are on old until the system is ready:");
15665 dumpProcessList(pw, this, mProcessesOnHold, " ",
15666 "OnHold Norm", "OnHold PERS", dumpPackage);
15667 }
15668
15669 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
15670
15671 needSep = mAppErrors.dumpLocked(fd, pw, needSep, dumpPackage);
15672 if (needSep) {
15673 printedAnything = true;
15674 }
15675
15676 if (dumpPackage == null) {
15677 pw.println();
15678 needSep = false;
15679 mUserController.dump(pw, dumpAll);
15680 }
15681 if (mHomeProcess != null && (dumpPackage == null
15682 || mHomeProcess.pkgList.containsKey(dumpPackage))) {
15683 if (needSep) {
15684 pw.println();
15685 needSep = false;
15686 }
15687 pw.println(" mHomeProcess: " + mHomeProcess);
15688 }
15689 if (mPreviousProcess != null && (dumpPackage == null
15690 || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
15691 if (needSep) {
15692 pw.println();
15693 needSep = false;
15694 }
15695 pw.println(" mPreviousProcess: " + mPreviousProcess);
15696 }
15697 if (dumpAll) {
15698 StringBuilder sb = new StringBuilder(128);
15699 sb.append(" mPreviousProcessVisibleTime: ");
15700 TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
15701 pw.println(sb);
15702 }
15703 if (mHeavyWeightProcess != null && (dumpPackage == null
15704 || mHeavyWeightProcess.pkgList.containsKey(dumpPackage))) {
15705 if (needSep) {
15706 pw.println();
15707 needSep = false;
15708 }
15709 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
15710 }
15711 if (dumpPackage == null) {
15712 pw.println(" mGlobalConfiguration: " + getGlobalConfiguration());
15713 mStackSupervisor.dumpDisplayConfigs(pw, " ");
15714 }
15715 if (dumpAll) {
15716 pw.println(" mConfigWillChange: " + getFocusedStack().mConfigWillChange);
15717 if (mCompatModePackages.getPackages().size() > 0) {
15718 boolean printed = false;
15719 for (Map.Entry<String, Integer> entry
15720 : mCompatModePackages.getPackages().entrySet()) {
15721 String pkg = entry.getKey();
15722 int mode = entry.getValue();
15723 if (dumpPackage != null && !dumpPackage.equals(pkg)) {
15724 continue;
15725 }
15726 if (!printed) {
15727 pw.println(" mScreenCompatPackages:");
15728 printed = true;
15729 }
15730 pw.print(" "); pw.print(pkg); pw.print(": ");
15731 pw.print(mode); pw.println();
15732 }
15733 }
15734 final int NI = mUidObservers.getRegisteredCallbackCount();
15735 boolean printed = false;
15736 for (int i=0; i<NI; i++) {
15737 final UidObserverRegistration reg = (UidObserverRegistration)
15738 mUidObservers.getRegisteredCallbackCookie(i);
15739 if (dumpPackage == null || dumpPackage.equals(reg.pkg)) {
15740 if (!printed) {
15741 pw.println(" mUidObservers:");
15742 printed = true;
15743 }
15744 pw.print(" "); UserHandle.formatUid(pw, reg.uid);
15745 pw.print(" "); pw.print(reg.pkg); pw.print(":");
15746 if ((reg.which&ActivityManager.UID_OBSERVER_IDLE) != 0) {
15747 pw.print(" IDLE");
15748 }
15749 if ((reg.which&ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
15750 pw.print(" ACT" );
15751 }
15752 if ((reg.which&ActivityManager.UID_OBSERVER_GONE) != 0) {
15753 pw.print(" GONE");
15754 }
15755 if ((reg.which&ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
15756 pw.print(" STATE");
15757 pw.print(" (cut="); pw.print(reg.cutpoint);
15758 pw.print(")");
15759 }
15760 pw.println();
15761 if (reg.lastProcStates != null) {
15762 final int NJ = reg.lastProcStates.size();
15763 for (int j=0; j<NJ; j++) {
15764 pw.print(" Last ");
15765 UserHandle.formatUid(pw, reg.lastProcStates.keyAt(j));
15766 pw.print(": "); pw.println(reg.lastProcStates.valueAt(j));
15767 }
15768 }
15769 }
15770 }
15771 pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
15772 pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
15773 if (mPendingTempWhitelist.size() > 0) {
15774 pw.println(" mPendingTempWhitelist:");
15775 for (int i = 0; i < mPendingTempWhitelist.size(); i++) {
15776 PendingTempWhitelist ptw = mPendingTempWhitelist.valueAt(i);
15777 pw.print(" ");
15778 UserHandle.formatUid(pw, ptw.targetUid);
15779 pw.print(": ");
15780 TimeUtils.formatDuration(ptw.duration, pw);
15781 pw.print(" ");
15782 pw.println(ptw.tag);
15783 }
15784 }
15785 }
15786 if (dumpPackage == null) {
15787 pw.println(" mWakefulness="
15788 + PowerManagerInternal.wakefulnessToString(mWakefulness));
15789 pw.println(" mSleepTokens=" + mSleepTokens);
15790 pw.println(" mSleeping=" + mSleeping);
15791 pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode);
15792 if (mRunningVoice != null) {
15793 pw.println(" mRunningVoice=" + mRunningVoice);
15794 pw.println(" mVoiceWakeLock" + mVoiceWakeLock);
15795 }
15796 }
15797 pw.println(" mVrController=" + mVrController);
15798 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
15799 || mOrigWaitForDebugger) {
15800 if (dumpPackage == null || dumpPackage.equals(mDebugApp)
15801 || dumpPackage.equals(mOrigDebugApp)) {
15802 if (needSep) {
15803 pw.println();
15804 needSep = false;
15805 }
15806 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
15807 + " mDebugTransient=" + mDebugTransient
15808 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
15809 }
15810 }
15811 if (mCurAppTimeTracker != null) {
15812 mCurAppTimeTracker.dumpWithHeader(pw, " ", true);
15813 }
15814 if (mMemWatchProcesses.getMap().size() > 0) {
15815 pw.println(" Mem watch processes:");
15816 final ArrayMap<String, SparseArray<Pair<Long, String>>> procs
15817 = mMemWatchProcesses.getMap();
15818 for (int i=0; i<procs.size(); i++) {
15819 final String proc = procs.keyAt(i);
15820 final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
15821 for (int j=0; j<uids.size(); j++) {
15822 if (needSep) {
15823 pw.println();
15824 needSep = false;
15825 }
15826 StringBuilder sb = new StringBuilder();
15827 sb.append(" ").append(proc).append('/');
15828 UserHandle.formatUid(sb, uids.keyAt(j));
15829 Pair<Long, String> val = uids.valueAt(j);
15830 sb.append(": "); DebugUtils.sizeValueToString(val.first, sb);
15831 if (val.second != null) {
15832 sb.append(", report to ").append(val.second);
15833 }
15834 pw.println(sb.toString());
15835 }
15836 }
15837 pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
15838 pw.print(" mMemWatchDumpFile="); pw.println(mMemWatchDumpFile);
15839 pw.print(" mMemWatchDumpPid="); pw.print(mMemWatchDumpPid);
15840 pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
15841 }
15842 if (mTrackAllocationApp != null) {
15843 if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
15844 if (needSep) {
15845 pw.println();
15846 needSep = false;
15847 }
15848 pw.println(" mTrackAllocationApp=" + mTrackAllocationApp);
15849 }
15850 }
15851 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
15852 || mProfileFd != null) {
15853 if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
15854 if (needSep) {
15855 pw.println();
15856 needSep = false;
15857 }
15858 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
15859 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
15860 pw.println(" mSamplingInterval=" + mSamplingInterval + " mAutoStopProfiler="
15861 + mAutoStopProfiler + " mStreamingOutput=" + mStreamingOutput);
15862 pw.println(" mProfileType=" + mProfileType);
15863 }
15864 }
15865 if (mNativeDebuggingApp != null) {
15866 if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) {
15867 if (needSep) {
15868 pw.println();
15869 needSep = false;
15870 }
15871 pw.println(" mNativeDebuggingApp=" + mNativeDebuggingApp);
15872 }
15873 }
15874 if (dumpPackage == null) {
15875 if (mAlwaysFinishActivities) {
15876 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities);
15877 }
15878 if (mController != null) {
15879 pw.println(" mController=" + mController
15880 + " mControllerIsAMonkey=" + mControllerIsAMonkey);
15881 }
15882 if (dumpAll) {
15883 pw.println(" Total persistent processes: " + numPers);
15884 pw.println(" mProcessesReady=" + mProcessesReady
15885 + " mSystemReady=" + mSystemReady
15886 + " mBooted=" + mBooted
15887 + " mFactoryTest=" + mFactoryTest);
15888 pw.println(" mBooting=" + mBooting
15889 + " mCallFinishBooting=" + mCallFinishBooting
15890 + " mBootAnimationComplete=" + mBootAnimationComplete);
15891 pw.print(" mLastPowerCheckRealtime=");
15892 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
15893 pw.println("");
15894 pw.print(" mLastPowerCheckUptime=");
15895 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
15896 pw.println("");
15897 pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
15898 pw.println(" mLaunchingActivity=" + mStackSupervisor.mLaunchingActivity);
15899 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
15900 pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
15901 + " (" + mLruProcesses.size() + " total)"
15902 + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
15903 + " mNumServiceProcs=" + mNumServiceProcs
15904 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
15905 pw.println(" mAllowLowerMemLevel=" + mAllowLowerMemLevel
15906 + " mLastMemoryLevel=" + mLastMemoryLevel
15907 + " mLastNumProcesses=" + mLastNumProcesses);
15908 long now = SystemClock.uptimeMillis();
15909 pw.print(" mLastIdleTime=");
15910 TimeUtils.formatDuration(now, mLastIdleTime, pw);
15911 pw.print(" mLowRamSinceLastIdle=");
15912 TimeUtils.formatDuration(getLowRamTimeSinceIdle(now), pw);
15913 pw.println();
15914 }
15915 }
15916
15917 if (!printedAnything) {
15918 pw.println(" (nothing)");
15919 }
15920 }
15921
15922 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
15923 int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
15924 if (mProcessesToGc.size() > 0) {
15925 boolean printed = false;
15926 long now = SystemClock.uptimeMillis();
15927 for (int i=0; i<mProcessesToGc.size(); i++) {
15928 ProcessRecord proc = mProcessesToGc.get(i);
15929 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
15930 continue;
15931 }
15932 if (!printed) {
15933 if (needSep) pw.println();
15934 needSep = true;
15935 pw.println(" Processes that are waiting to GC:");
15936 printed = true;
15937 }
15938 pw.print(" Process "); pw.println(proc);
15939 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
15940 pw.print(", last gced=");
15941 pw.print(now-proc.lastRequestedGc);
15942 pw.print(" ms ago, last lowMem=");
15943 pw.print(now-proc.lastLowMemory);
15944 pw.println(" ms ago");
15945
15946 }
15947 }
15948 return needSep;
15949 }
15950
15951 void printOomLevel(PrintWriter pw, String name, int adj) {
15952 pw.print(" ");
15953 if (adj >= 0) {
15954 pw.print(' ');
15955 if (adj < 10) pw.print(' ');
15956 } else {
15957 if (adj > -10) pw.print(' ');
15958 }
15959 pw.print(adj);
15960 pw.print(": ");
15961 pw.print(name);
15962 pw.print(" (");
15963 pw.print(stringifySize(mProcessList.getMemLevel(adj), 1024));
15964 pw.println(")");
15965 }
15966
15967 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
15968 int opti, boolean dumpAll) {
15969 boolean needSep = false;
15970
15971 if (mLruProcesses.size() > 0) {
15972 if (needSep) pw.println();
15973 needSep = true;
15974 pw.println(" OOM levels:");
15975 printOomLevel(pw, "SYSTEM_ADJ", ProcessList.SYSTEM_ADJ);
15976 printOomLevel(pw, "PERSISTENT_PROC_ADJ", ProcessList.PERSISTENT_PROC_ADJ);
15977 printOomLevel(pw, "PERSISTENT_SERVICE_ADJ", ProcessList.PERSISTENT_SERVICE_ADJ);
15978 printOomLevel(pw, "FOREGROUND_APP_ADJ", ProcessList.FOREGROUND_APP_ADJ);
15979 printOomLevel(pw, "VISIBLE_APP_ADJ", ProcessList.VISIBLE_APP_ADJ);
15980 printOomLevel(pw, "PERCEPTIBLE_APP_ADJ", ProcessList.PERCEPTIBLE_APP_ADJ);
15981 printOomLevel(pw, "BACKUP_APP_ADJ", ProcessList.BACKUP_APP_ADJ);
15982 printOomLevel(pw, "HEAVY_WEIGHT_APP_ADJ", ProcessList.HEAVY_WEIGHT_APP_ADJ);
15983 printOomLevel(pw, "SERVICE_ADJ", ProcessList.SERVICE_ADJ);
15984 printOomLevel(pw, "HOME_APP_ADJ", ProcessList.HOME_APP_ADJ);
15985 printOomLevel(pw, "PREVIOUS_APP_ADJ", ProcessList.PREVIOUS_APP_ADJ);
15986 printOomLevel(pw, "SERVICE_B_ADJ", ProcessList.SERVICE_B_ADJ);
15987 printOomLevel(pw, "CACHED_APP_MIN_ADJ", ProcessList.CACHED_APP_MIN_ADJ);
15988 printOomLevel(pw, "CACHED_APP_MAX_ADJ", ProcessList.CACHED_APP_MAX_ADJ);
15989
15990 if (needSep) pw.println();
15991 pw.print(" Process OOM control ("); pw.print(mLruProcesses.size());
15992 pw.print(" total, non-act at ");
15993 pw.print(mLruProcesses.size()-mLruProcessActivityStart);
15994 pw.print(", non-svc at ");
15995 pw.print(mLruProcesses.size()-mLruProcessServiceStart);
15996 pw.println("):");
15997 dumpProcessOomList(pw, this, mLruProcesses, " ", "Proc", "PERS", true, null);
15998 needSep = true;
15999 }
16000
16001 dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
16002
16003 pw.println();
16004 pw.println(" mHomeProcess: " + mHomeProcess);
16005 pw.println(" mPreviousProcess: " + mPreviousProcess);
16006 if (mHeavyWeightProcess != null) {
16007 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
16008 }
16009
16010 return true;
16011 }
16012
16013 /**
16014 * There are three ways to call this:
16015 * - no provider specified: dump all the providers
16016 * - a flattened component name that matched an existing provider was specified as the
16017 * first arg: dump that one provider
16018 * - the first arg isn't the flattened component name of an existing provider:
16019 * dump all providers whose component contains the first arg as a substring
16020 */
16021 protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
16022 int opti, boolean dumpAll) {
16023 return mProviderMap.dumpProvider(fd, pw, name, args, opti, dumpAll);
16024 }
16025
16026 static class ItemMatcher {
16027 ArrayList<ComponentName> components;
16028 ArrayList<String> strings;
16029 ArrayList<Integer> objects;
16030 boolean all;
16031
16032 ItemMatcher() {
16033 all = true;
16034 }
16035
16036 void build(String name) {
16037 ComponentName componentName = ComponentName.unflattenFromString(name);
16038 if (componentName != null) {
16039 if (components == null) {
16040 components = new ArrayList<ComponentName>();
16041 }
16042 components.add(componentName);
16043 all = false;
16044 } else {
16045 int objectId = 0;
16046 // Not a '/' separated full component name; maybe an object ID?
16047 try {
16048 objectId = Integer.parseInt(name, 16);
16049 if (objects == null) {
16050 objects = new ArrayList<Integer>();
16051 }
16052 objects.add(objectId);
16053 all = false;
16054 } catch (RuntimeException e) {
16055 // Not an integer; just do string match.
16056 if (strings == null) {
16057 strings = new ArrayList<String>();
16058 }
16059 strings.add(name);
16060 all = false;
16061 }
16062 }
16063 }
16064
16065 int build(String[] args, int opti) {
16066 for (; opti<args.length; opti++) {
16067 String name = args[opti];
16068 if ("--".equals(name)) {
16069 return opti+1;
16070 }
16071 build(name);
16072 }
16073 return opti;
16074 }
16075
16076 boolean match(Object object, ComponentName comp) {
16077 if (all) {
16078 return true;
16079 }
16080 if (components != null) {
16081 for (int i=0; i<components.size(); i++) {
16082 if (components.get(i).equals(comp)) {
16083 return true;
16084 }
16085 }
16086 }
16087 if (objects != null) {
16088 for (int i=0; i<objects.size(); i++) {
16089 if (System.identityHashCode(object) == objects.get(i)) {
16090 return true;
16091 }
16092 }
16093 }
16094 if (strings != null) {
16095 String flat = comp.flattenToString();
16096 for (int i=0; i<strings.size(); i++) {
16097 if (flat.contains(strings.get(i))) {
16098 return true;
16099 }
16100 }
16101 }
16102 return false;
16103 }
16104 }
16105
16106 /**
16107 * There are three things that cmd can be:
16108 * - a flattened component name that matches an existing activity
16109 * - the cmd arg isn't the flattened component name of an existing activity:
16110 * dump all activity whose component contains the cmd as a substring
16111 * - A hex number of the ActivityRecord object instance.
16112 *
16113 * @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack
16114 * @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack
16115 */
16116 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
16117 int opti, boolean dumpAll, boolean dumpVisibleStacksOnly, boolean dumpFocusedStackOnly) {
16118 ArrayList<ActivityRecord> activities;
16119
16120 synchronized (this) {
16121 activities = mStackSupervisor.getDumpActivitiesLocked(name, dumpVisibleStacksOnly,
16122 dumpFocusedStackOnly);
16123 }
16124
16125 if (activities.size() <= 0) {
16126 return false;
16127 }
16128
16129 String[] newArgs = new String[args.length - opti];
16130 System.arraycopy(args, opti, newArgs, 0, args.length - opti);
16131
16132 TaskRecord lastTask = null;
16133 boolean needSep = false;
16134 for (int i=activities.size()-1; i>=0; i--) {
16135 ActivityRecord r = activities.get(i);
16136 if (needSep) {
16137 pw.println();
16138 }
16139 needSep = true;
16140 synchronized (this) {
16141 final TaskRecord task = r.getTask();
16142 if (lastTask != task) {
16143 lastTask = task;
16144 pw.print("TASK "); pw.print(lastTask.affinity);
16145 pw.print(" id="); pw.print(lastTask.taskId);
16146 pw.print(" userId="); pw.println(lastTask.userId);
16147 if (dumpAll) {
16148 lastTask.dump(pw, " ");
16149 }
16150 }
16151 }
16152 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
16153 }
16154 return true;
16155 }
16156
16157 /**
16158 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
16159 * there is a thread associated with the activity.
16160 */
16161 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
16162 final ActivityRecord r, String[] args, boolean dumpAll) {
16163 String innerPrefix = prefix + " ";
16164 synchronized (this) {
16165 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
16166 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
16167 pw.print(" pid=");
16168 if (r.app != null) pw.println(r.app.pid);
16169 else pw.println("(not running)");
16170 if (dumpAll) {
16171 r.dump(pw, innerPrefix);
16172 }
16173 }
16174 if (r.app != null && r.app.thread != null) {
16175 // flush anything that is already in the PrintWriter since the thread is going
16176 // to write to the file descriptor directly
16177 pw.flush();
16178 try {
16179 TransferPipe tp = new TransferPipe();
16180 try {
16181 r.app.thread.dumpActivity(tp.getWriteFd(),
16182 r.appToken, innerPrefix, args);
16183 tp.go(fd);
16184 } finally {
16185 tp.kill();
16186 }
16187 } catch (IOException e) {
16188 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
16189 } catch (RemoteException e) {
16190 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
16191 }
16192 }
16193 }
16194
16195 void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16196 int opti, boolean dumpAll, String dumpPackage) {
16197 boolean needSep = false;
16198 boolean onlyHistory = false;
16199 boolean printedAnything = false;
16200
16201 if ("history".equals(dumpPackage)) {
16202 if (opti < args.length && "-s".equals(args[opti])) {
16203 dumpAll = false;
16204 }
16205 onlyHistory = true;
16206 dumpPackage = null;
16207 }
16208
16209 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
16210 if (!onlyHistory && dumpAll) {
16211 if (mRegisteredReceivers.size() > 0) {
16212 boolean printed = false;
16213 Iterator it = mRegisteredReceivers.values().iterator();
16214 while (it.hasNext()) {
16215 ReceiverList r = (ReceiverList)it.next();
16216 if (dumpPackage != null && (r.app == null ||
16217 !dumpPackage.equals(r.app.info.packageName))) {
16218 continue;
16219 }
16220 if (!printed) {
16221 pw.println(" Registered Receivers:");
16222 needSep = true;
16223 printed = true;
16224 printedAnything = true;
16225 }
16226 pw.print(" * "); pw.println(r);
16227 r.dump(pw, " ");
16228 }
16229 }
16230
16231 if (mReceiverResolver.dump(pw, needSep ?
16232 "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
16233 " ", dumpPackage, false, false)) {
16234 needSep = true;
16235 printedAnything = true;
16236 }
16237 }
16238
16239 for (BroadcastQueue q : mBroadcastQueues) {
16240 needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep);
16241 printedAnything |= needSep;
16242 }
16243
16244 needSep = true;
16245
16246 if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) {
16247 for (int user=0; user<mStickyBroadcasts.size(); user++) {
16248 if (needSep) {
16249 pw.println();
16250 }
16251 needSep = true;
16252 printedAnything = true;
16253 pw.print(" Sticky broadcasts for user ");
16254 pw.print(mStickyBroadcasts.keyAt(user)); pw.println(":");
16255 StringBuilder sb = new StringBuilder(128);
16256 for (Map.Entry<String, ArrayList<Intent>> ent
16257 : mStickyBroadcasts.valueAt(user).entrySet()) {
16258 pw.print(" * Sticky action "); pw.print(ent.getKey());
16259 if (dumpAll) {
16260 pw.println(":");
16261 ArrayList<Intent> intents = ent.getValue();
16262 final int N = intents.size();
16263 for (int i=0; i<N; i++) {
16264 sb.setLength(0);
16265 sb.append(" Intent: ");
16266 intents.get(i).toShortString(sb, false, true, false, false);
16267 pw.println(sb.toString());
16268 Bundle bundle = intents.get(i).getExtras();
16269 if (bundle != null) {
16270 pw.print(" ");
16271 pw.println(bundle.toString());
16272 }
16273 }
16274 } else {
16275 pw.println("");
16276 }
16277 }
16278 }
16279 }
16280
16281 if (!onlyHistory && dumpAll) {
16282 pw.println();
16283 for (BroadcastQueue queue : mBroadcastQueues) {
16284 pw.println(" mBroadcastsScheduled [" + queue.mQueueName + "]="
16285 + queue.mBroadcastsScheduled);
16286 }
16287 pw.println(" mHandler:");
16288 mHandler.dump(new PrintWriterPrinter(pw), " ");
16289 needSep = true;
16290 printedAnything = true;
16291 }
16292
16293 if (!printedAnything) {
16294 pw.println(" (nothing)");
16295 }
16296 }
16297
16298 void dumpBroadcastStatsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16299 int opti, boolean dumpAll, String dumpPackage) {
16300 if (mCurBroadcastStats == null) {
16301 return;
16302 }
16303
16304 pw.println("ACTIVITY MANAGER BROADCAST STATS STATE (dumpsys activity broadcast-stats)");
16305 final long now = SystemClock.elapsedRealtime();
16306 if (mLastBroadcastStats != null) {
16307 pw.print(" Last stats (from ");
16308 TimeUtils.formatDuration(mLastBroadcastStats.mStartRealtime, now, pw);
16309 pw.print(" to ");
16310 TimeUtils.formatDuration(mLastBroadcastStats.mEndRealtime, now, pw);
16311 pw.print(", ");
16312 TimeUtils.formatDuration(mLastBroadcastStats.mEndUptime
16313 - mLastBroadcastStats.mStartUptime, pw);
16314 pw.println(" uptime):");
16315 if (!mLastBroadcastStats.dumpStats(pw, " ", dumpPackage)) {
16316 pw.println(" (nothing)");
16317 }
16318 pw.println();
16319 }
16320 pw.print(" Current stats (from ");
16321 TimeUtils.formatDuration(mCurBroadcastStats.mStartRealtime, now, pw);
16322 pw.print(" to now, ");
16323 TimeUtils.formatDuration(SystemClock.uptimeMillis()
16324 - mCurBroadcastStats.mStartUptime, pw);
16325 pw.println(" uptime):");
16326 if (!mCurBroadcastStats.dumpStats(pw, " ", dumpPackage)) {
16327 pw.println(" (nothing)");
16328 }
16329 }
16330
16331 void dumpBroadcastStatsCheckinLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16332 int opti, boolean fullCheckin, String dumpPackage) {
16333 if (mCurBroadcastStats == null) {
16334 return;
16335 }
16336
16337 if (mLastBroadcastStats != null) {
16338 mLastBroadcastStats.dumpCheckinStats(pw, dumpPackage);
16339 if (fullCheckin) {
16340 mLastBroadcastStats = null;
16341 return;
16342 }
16343 }
16344 mCurBroadcastStats.dumpCheckinStats(pw, dumpPackage);
16345 if (fullCheckin) {
16346 mCurBroadcastStats = null;
16347 }
16348 }
16349
16350 void dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16351 int opti, boolean dumpAll, String dumpPackage) {
16352 boolean needSep;
16353 boolean printedAnything = false;
16354
16355 ItemMatcher matcher = new ItemMatcher();
16356 matcher.build(args, opti);
16357
16358 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
16359
16360 needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
16361 printedAnything |= needSep;
16362
16363 if (mLaunchingProviders.size() > 0) {
16364 boolean printed = false;
16365 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
16366 ContentProviderRecord r = mLaunchingProviders.get(i);
16367 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
16368 continue;
16369 }
16370 if (!printed) {
16371 if (needSep) pw.println();
16372 needSep = true;
16373 pw.println(" Launching content providers:");
16374 printed = true;
16375 printedAnything = true;
16376 }
16377 pw.print(" Launching #"); pw.print(i); pw.print(": ");
16378 pw.println(r);
16379 }
16380 }
16381
16382 if (!printedAnything) {
16383 pw.println(" (nothing)");
16384 }
16385 }
16386
16387 void dumpPermissionsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16388 int opti, boolean dumpAll, String dumpPackage) {
16389 boolean needSep = false;
16390 boolean printedAnything = false;
16391
16392 pw.println("ACTIVITY MANAGER URI PERMISSIONS (dumpsys activity permissions)");
16393
16394 if (mGrantedUriPermissions.size() > 0) {
16395 boolean printed = false;
16396 int dumpUid = -2;
16397 if (dumpPackage != null) {
16398 try {
16399 dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage,
16400 MATCH_ANY_USER, 0);
16401 } catch (NameNotFoundException e) {
16402 dumpUid = -1;
16403 }
16404 }
16405 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
16406 int uid = mGrantedUriPermissions.keyAt(i);
16407 if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
16408 continue;
16409 }
16410 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
16411 if (!printed) {
16412 if (needSep) pw.println();
16413 needSep = true;
16414 pw.println(" Granted Uri Permissions:");
16415 printed = true;
16416 printedAnything = true;
16417 }
16418 pw.print(" * UID "); pw.print(uid); pw.println(" holds:");
16419 for (UriPermission perm : perms.values()) {
16420 pw.print(" "); pw.println(perm);
16421 if (dumpAll) {
16422 perm.dump(pw, " ");
16423 }
16424 }
16425 }
16426 }
16427
16428 if (!printedAnything) {
16429 pw.println(" (nothing)");
16430 }
16431 }
16432
16433 void dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
16434 int opti, boolean dumpAll, String dumpPackage) {
16435 boolean printed = false;
16436
16437 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
16438
16439 if (mIntentSenderRecords.size() > 0) {
16440 // Organize these by package name, so they are easier to read.
16441 final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>();
16442 final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>();
16443 final Iterator<WeakReference<PendingIntentRecord>> it
16444 = mIntentSenderRecords.values().iterator();
16445 while (it.hasNext()) {
16446 WeakReference<PendingIntentRecord> ref = it.next();
16447 PendingIntentRecord rec = ref != null ? ref.get() : null;
16448 if (rec == null) {
16449 weakRefs.add(ref);
16450 continue;
16451 }
16452 if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) {
16453 continue;
16454 }
16455 ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName);
16456 if (list == null) {
16457 list = new ArrayList<>();
16458 byPackage.put(rec.key.packageName, list);
16459 }
16460 list.add(rec);
16461 }
16462 for (int i = 0; i < byPackage.size(); i++) {
16463 ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i);
16464 printed = true;
16465 pw.print(" * "); pw.print(byPackage.keyAt(i));
16466 pw.print(": "); pw.print(intents.size()); pw.println(" items");
16467 for (int j = 0; j < intents.size(); j++) {
16468 pw.print(" #"); pw.print(j); pw.print(": "); pw.println(intents.get(j));
16469 if (dumpAll) {
16470 intents.get(j).dump(pw, " ");
16471 }
16472 }
16473 }
16474 if (weakRefs.size() > 0) {
16475 printed = true;
16476 pw.println(" * WEAK REFS:");
16477 for (int i = 0; i < weakRefs.size(); i++) {
16478 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i));
16479 }
16480 }
16481 }
16482
16483 if (!printed) {
16484 pw.println(" (nothing)");
16485 }
16486 }
16487
16488 private static final int dumpProcessList(PrintWriter pw,
16489 ActivityManagerService service, List list,
16490 String prefix, String normalLabel, String persistentLabel,
16491 String dumpPackage) {
16492 int numPers = 0;
16493 final int N = list.size()-1;
16494 for (int i=N; i>=0; i--) {
16495 ProcessRecord r = (ProcessRecord)list.get(i);
16496 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
16497 continue;
16498 }
16499 pw.println(String.format("%s%s #%2d: %s",
16500 prefix, (r.persistent ? persistentLabel : normalLabel),
16501 i, r.toString()));
16502 if (r.persistent) {
16503 numPers++;
16504 }
16505 }
16506 return numPers;
16507 }
16508
16509 private static final boolean dumpProcessOomList(PrintWriter pw,
16510 ActivityManagerService service, List<ProcessRecord> origList,
16511 String prefix, String normalLabel, String persistentLabel,
16512 boolean inclDetails, String dumpPackage) {
16513
16514 ArrayList<Pair<ProcessRecord, Integer>> list
16515 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
16516 for (int i=0; i<origList.size(); i++) {
16517 ProcessRecord r = origList.get(i);
16518 if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
16519 continue;
16520 }
16521 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
16522 }
16523
16524 if (list.size() <= 0) {
16525 return false;
16526 }
16527
16528 Comparator<Pair<ProcessRecord, Integer>> comparator
16529 = new Comparator<Pair<ProcessRecord, Integer>>() {
16530 @Override
16531 public int compare(Pair<ProcessRecord, Integer> object1,
16532 Pair<ProcessRecord, Integer> object2) {
16533 if (object1.first.setAdj != object2.first.setAdj) {
16534 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
16535 }
16536 if (object1.first.setProcState != object2.first.setProcState) {
16537 return object1.first.setProcState > object2.first.setProcState ? -1 : 1;
16538 }
16539 if (object1.second.intValue() != object2.second.intValue()) {
16540 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
16541 }
16542 return 0;
16543 }
16544 };
16545
16546 Collections.sort(list, comparator);
16547
16548 final long curRealtime = SystemClock.elapsedRealtime();
16549 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
16550 final long curUptime = SystemClock.uptimeMillis();
16551 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
16552
16553 for (int i=list.size()-1; i>=0; i--) {
16554 ProcessRecord r = list.get(i).first;
16555 String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
16556 char schedGroup;
16557 switch (r.setSchedGroup) {
16558 case ProcessList.SCHED_GROUP_BACKGROUND:
16559 schedGroup = 'B';
16560 break;
16561 case ProcessList.SCHED_GROUP_DEFAULT:
16562 schedGroup = 'F';
16563 break;
16564 case ProcessList.SCHED_GROUP_TOP_APP:
16565 schedGroup = 'T';
16566 break;
16567 default:
16568 schedGroup = '?';
16569 break;
16570 }
16571 char foreground;
16572 if (r.foregroundActivities) {
16573 foreground = 'A';
16574 } else if (r.foregroundServices) {
16575 foreground = 'S';
16576 } else {
16577 foreground = ' ';
16578 }
16579 String procState = ProcessList.makeProcStateString(r.curProcState);
16580 pw.print(prefix);
16581 pw.print(r.persistent ? persistentLabel : normalLabel);
16582 pw.print(" #");
16583 int num = (origList.size()-1)-list.get(i).second;
16584 if (num < 10) pw.print(' ');
16585 pw.print(num);
16586 pw.print(": ");
16587 pw.print(oomAdj);
16588 pw.print(' ');
16589 pw.print(schedGroup);
16590 pw.print('/');
16591 pw.print(foreground);
16592 pw.print('/');
16593 pw.print(procState);
16594 pw.print(" trm:");
16595 if (r.trimMemoryLevel < 10) pw.print(' ');
16596 pw.print(r.trimMemoryLevel);
16597 pw.print(' ');
16598 pw.print(r.toShortString());
16599 pw.print(" (");
16600 pw.print(r.adjType);
16601 pw.println(')');
16602 if (r.adjSource != null || r.adjTarget != null) {
16603 pw.print(prefix);
16604 pw.print(" ");
16605 if (r.adjTarget instanceof ComponentName) {
16606 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
16607 } else if (r.adjTarget != null) {
16608 pw.print(r.adjTarget.toString());
16609 } else {
16610 pw.print("{null}");
16611 }
16612 pw.print("<=");
16613 if (r.adjSource instanceof ProcessRecord) {
16614 pw.print("Proc{");
16615 pw.print(((ProcessRecord)r.adjSource).toShortString());
16616 pw.println("}");
16617 } else if (r.adjSource != null) {
16618 pw.println(r.adjSource.toString());
16619 } else {
16620 pw.println("{null}");
16621 }
16622 }
16623 if (inclDetails) {
16624 pw.print(prefix);
16625 pw.print(" ");
16626 pw.print("oom: max="); pw.print(r.maxAdj);
16627 pw.print(" curRaw="); pw.print(r.curRawAdj);
16628 pw.print(" setRaw="); pw.print(r.setRawAdj);
16629 pw.print(" cur="); pw.print(r.curAdj);
16630 pw.print(" set="); pw.println(r.setAdj);
16631 pw.print(prefix);
16632 pw.print(" ");
16633 pw.print("state: cur="); pw.print(ProcessList.makeProcStateString(r.curProcState));
16634 pw.print(" set="); pw.print(ProcessList.makeProcStateString(r.setProcState));
16635 pw.print(" lastPss="); DebugUtils.printSizeValue(pw, r.lastPss*1024);
16636 pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, r.lastSwapPss*1024);
16637 pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, r.lastCachedPss*1024);
16638 pw.println();
16639 pw.print(prefix);
16640 pw.print(" ");
16641 pw.print("cached="); pw.print(r.cached);
16642 pw.print(" empty="); pw.print(r.empty);
16643 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
16644
16645 if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
16646 if (r.lastWakeTime != 0) {
16647 long wtime;
16648 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
16649 synchronized (stats) {
16650 wtime = stats.getProcessWakeTime(r.info.uid,
16651 r.pid, curRealtime);
16652 }
16653 long timeUsed = wtime - r.lastWakeTime;
16654 pw.print(prefix);
16655 pw.print(" ");
16656 pw.print("keep awake over ");
16657 TimeUtils.formatDuration(realtimeSince, pw);
16658 pw.print(" used ");
16659 TimeUtils.formatDuration(timeUsed, pw);
16660 pw.print(" (");
16661 pw.print((timeUsed*100)/realtimeSince);
16662 pw.println("%)");
16663 }
16664 if (r.lastCpuTime != 0) {
16665 long timeUsed = r.curCpuTime - r.lastCpuTime;
16666 pw.print(prefix);
16667 pw.print(" ");
16668 pw.print("run cpu over ");
16669 TimeUtils.formatDuration(uptimeSince, pw);
16670 pw.print(" used ");
16671 TimeUtils.formatDuration(timeUsed, pw);
16672 pw.print(" (");
16673 pw.print((timeUsed*100)/uptimeSince);
16674 pw.println("%)");
16675 }
16676 }
16677 }
16678 }
16679 return true;
16680 }
16681
16682 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, boolean allPkgs,
16683 String[] args) {
16684 ArrayList<ProcessRecord> procs;
16685 synchronized (this) {
16686 if (args != null && args.length > start
16687 && args[start].charAt(0) != '-') {
16688 procs = new ArrayList<ProcessRecord>();
16689 int pid = -1;
16690 try {
16691 pid = Integer.parseInt(args[start]);
16692 } catch (NumberFormatException e) {
16693 }
16694 for (int i=mLruProcesses.size()-1; i>=0; i--) {
16695 ProcessRecord proc = mLruProcesses.get(i);
16696 if (proc.pid == pid) {
16697 procs.add(proc);
16698 } else if (allPkgs && proc.pkgList != null
16699 && proc.pkgList.containsKey(args[start])) {
16700 procs.add(proc);
16701 } else if (proc.processName.equals(args[start])) {
16702 procs.add(proc);
16703 }
16704 }
16705 if (procs.size() <= 0) {
16706 return null;
16707 }
16708 } else {
16709 procs = new ArrayList<ProcessRecord>(mLruProcesses);
16710 }
16711 }
16712 return procs;
16713 }
16714
16715 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
16716 PrintWriter pw, String[] args) {
16717 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, false, args);
16718 if (procs == null) {
16719 pw.println("No process found for: " + args[0]);
16720 return;
16721 }
16722
16723 long uptime = SystemClock.uptimeMillis();
16724 long realtime = SystemClock.elapsedRealtime();
16725 pw.println("Applications Graphics Acceleration Info:");
16726 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
16727
16728 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
16729 ProcessRecord r = procs.get(i);
16730 if (r.thread != null) {
16731 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
16732 pw.flush();
16733 try {
16734 TransferPipe tp = new TransferPipe();
16735 try {
16736 r.thread.dumpGfxInfo(tp.getWriteFd(), args);
16737 tp.go(fd);
16738 } finally {
16739 tp.kill();
16740 }
16741 } catch (IOException e) {
16742 pw.println("Failure while dumping the app: " + r);
16743 pw.flush();
16744 } catch (RemoteException e) {
16745 pw.println("Got a RemoteException while dumping the app " + r);
16746 pw.flush();
16747 }
16748 }
16749 }
16750 }
16751
16752 final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
16753 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, false, args);
16754 if (procs == null) {
16755 pw.println("No process found for: " + args[0]);
16756 return;
16757 }
16758
16759 pw.println("Applications Database Info:");
16760
16761 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
16762 ProcessRecord r = procs.get(i);
16763 if (r.thread != null) {
16764 pw.println("\n** Database info for pid " + r.pid + " [" + r.processName + "] **");
16765 pw.flush();
16766 try {
16767 TransferPipe tp = new TransferPipe();
16768 try {
16769 r.thread.dumpDbInfo(tp.getWriteFd(), args);
16770 tp.go(fd);
16771 } finally {
16772 tp.kill();
16773 }
16774 } catch (IOException e) {
16775 pw.println("Failure while dumping the app: " + r);
16776 pw.flush();
16777 } catch (RemoteException e) {
16778 pw.println("Got a RemoteException while dumping the app " + r);
16779 pw.flush();
16780 }
16781 }
16782 }
16783 }
16784
16785 final static class MemItem {
16786 final boolean isProc;
16787 final String label;
16788 final String shortLabel;
16789 final long pss;
16790 final long swapPss;
16791 final int id;
16792 final boolean hasActivities;
16793 ArrayList<MemItem> subitems;
16794
16795 public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id,
16796 boolean _hasActivities) {
16797 isProc = true;
16798 label = _label;
16799 shortLabel = _shortLabel;
16800 pss = _pss;
16801 swapPss = _swapPss;
16802 id = _id;
16803 hasActivities = _hasActivities;
16804 }
16805
16806 public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id) {
16807 isProc = false;
16808 label = _label;
16809 shortLabel = _shortLabel;
16810 pss = _pss;
16811 swapPss = _swapPss;
16812 id = _id;
16813 hasActivities = false;
16814 }
16815 }
16816
16817 static final void dumpMemItems(PrintWriter pw, String prefix, String tag,
16818 ArrayList<MemItem> items, boolean sort, boolean isCompact, boolean dumpSwapPss) {
16819 if (sort && !isCompact) {
16820 Collections.sort(items, new Comparator<MemItem>() {
16821 @Override
16822 public int compare(MemItem lhs, MemItem rhs) {
16823 if (lhs.pss < rhs.pss) {
16824 return 1;
16825 } else if (lhs.pss > rhs.pss) {
16826 return -1;
16827 }
16828 return 0;
16829 }
16830 });
16831 }
16832
16833 for (int i=0; i<items.size(); i++) {
16834 MemItem mi = items.get(i);
16835 if (!isCompact) {
16836 if (dumpSwapPss) {
16837 pw.printf("%s%s: %-60s (%s in swap)\n", prefix, stringifyKBSize(mi.pss),
16838 mi.label, stringifyKBSize(mi.swapPss));
16839 } else {
16840 pw.printf("%s%s: %s\n", prefix, stringifyKBSize(mi.pss), mi.label);
16841 }
16842 } else if (mi.isProc) {
16843 pw.print("proc,"); pw.print(tag); pw.print(","); pw.print(mi.shortLabel);
16844 pw.print(","); pw.print(mi.id); pw.print(","); pw.print(mi.pss); pw.print(",");
16845 pw.print(dumpSwapPss ? mi.swapPss : "N/A");
16846 pw.println(mi.hasActivities ? ",a" : ",e");
16847 } else {
16848 pw.print(tag); pw.print(","); pw.print(mi.shortLabel); pw.print(",");
16849 pw.print(mi.pss); pw.print(","); pw.println(dumpSwapPss ? mi.swapPss : "N/A");
16850 }
16851 if (mi.subitems != null) {
16852 dumpMemItems(pw, prefix + " ", mi.shortLabel, mi.subitems,
16853 true, isCompact, dumpSwapPss);
16854 }
16855 }
16856 }
16857
16858 // These are in KB.
16859 static final long[] DUMP_MEM_BUCKETS = new long[] {
16860 5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
16861 120*1024, 160*1024, 200*1024,
16862 250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
16863 1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
16864 };
16865
16866 static final void appendMemBucket(StringBuilder out, long memKB, String label,
16867 boolean stackLike) {
16868 int start = label.lastIndexOf('.');
16869 if (start >= 0) start++;
16870 else start = 0;
16871 int end = label.length();
16872 for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
16873 if (DUMP_MEM_BUCKETS[i] >= memKB) {
16874 long bucket = DUMP_MEM_BUCKETS[i]/1024;
16875 out.append(bucket);
16876 out.append(stackLike ? "MB." : "MB ");
16877 out.append(label, start, end);
16878 return;
16879 }
16880 }
16881 out.append(memKB/1024);
16882 out.append(stackLike ? "MB." : "MB ");
16883 out.append(label, start, end);
16884 }
16885
16886 static final int[] DUMP_MEM_OOM_ADJ = new int[] {
16887 ProcessList.NATIVE_ADJ,
16888 ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ,
16889 ProcessList.PERSISTENT_SERVICE_ADJ, ProcessList.FOREGROUND_APP_ADJ,
16890 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ,
16891 ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
16892 ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
16893 ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MIN_ADJ
16894 };
16895 static final String[] DUMP_MEM_OOM_LABEL = new String[] {
16896 "Native",
16897 "System", "Persistent", "Persistent Service", "Foreground",
16898 "Visible", "Perceptible",
16899 "Heavy Weight", "Backup",
16900 "A Services", "Home",
16901 "Previous", "B Services", "Cached"
16902 };
16903 static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
16904 "native",
16905 "sys", "pers", "persvc", "fore",
16906 "vis", "percept",
16907 "heavy", "backup",
16908 "servicea", "home",
16909 "prev", "serviceb", "cached"
16910 };
16911
16912 private final void dumpApplicationMemoryUsageHeader(PrintWriter pw, long uptime,
16913 long realtime, boolean isCheckinRequest, boolean isCompact) {
16914 if (isCompact) {
16915 pw.print("version,"); pw.println(MEMINFO_COMPACT_VERSION);
16916 }
16917 if (isCheckinRequest || isCompact) {
16918 // short checkin version
16919 pw.print("time,"); pw.print(uptime); pw.print(","); pw.println(realtime);
16920 } else {
16921 pw.println("Applications Memory Usage (in Kilobytes):");
16922 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
16923 }
16924 }
16925
16926 private static final int KSM_SHARED = 0;
16927 private static final int KSM_SHARING = 1;
16928 private static final int KSM_UNSHARED = 2;
16929 private static final int KSM_VOLATILE = 3;
16930
16931 private final long[] getKsmInfo() {
16932 long[] longOut = new long[4];
16933 final int[] SINGLE_LONG_FORMAT = new int[] {
16934 PROC_SPACE_TERM| PROC_OUT_LONG
16935 };
16936 long[] longTmp = new long[1];
16937 readProcFile("/sys/kernel/mm/ksm/pages_shared",
16938 SINGLE_LONG_FORMAT, null, longTmp, null);
16939 longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
16940 longTmp[0] = 0;
16941 readProcFile("/sys/kernel/mm/ksm/pages_sharing",
16942 SINGLE_LONG_FORMAT, null, longTmp, null);
16943 longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
16944 longTmp[0] = 0;
16945 readProcFile("/sys/kernel/mm/ksm/pages_unshared",
16946 SINGLE_LONG_FORMAT, null, longTmp, null);
16947 longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
16948 longTmp[0] = 0;
16949 readProcFile("/sys/kernel/mm/ksm/pages_volatile",
16950 SINGLE_LONG_FORMAT, null, longTmp, null);
16951 longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
16952 return longOut;
16953 }
16954
16955 private static String stringifySize(long size, int order) {
16956 Locale locale = Locale.US;
16957 switch (order) {
16958 case 1:
16959 return String.format(locale, "%,13d", size);
16960 case 1024:
16961 return String.format(locale, "%,9dK", size / 1024);
16962 case 1024 * 1024:
16963 return String.format(locale, "%,5dM", size / 1024 / 1024);
16964 case 1024 * 1024 * 1024:
16965 return String.format(locale, "%,1dG", size / 1024 / 1024 / 1024);
16966 default:
16967 throw new IllegalArgumentException("Invalid size order");
16968 }
16969 }
16970
16971 private static String stringifyKBSize(long size) {
16972 return stringifySize(size * 1024, 1024);
16973 }
16974
16975 // Update this version number in case you change the 'compact' format
16976 private static final int MEMINFO_COMPACT_VERSION = 1;
16977
16978 final void dumpApplicationMemoryUsage(FileDescriptor fd,
16979 PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
16980 boolean dumpDetails = false;
16981 boolean dumpFullDetails = false;
16982 boolean dumpDalvik = false;
16983 boolean dumpSummaryOnly = false;
16984 boolean dumpUnreachable = false;
16985 boolean oomOnly = false;
16986 boolean isCompact = false;
16987 boolean localOnly = false;
16988 boolean packages = false;
16989 boolean isCheckinRequest = false;
16990 boolean dumpSwapPss = false;
16991
16992 int opti = 0;
16993 while (opti < args.length) {
16994 String opt = args[opti];
16995 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
16996 break;
16997 }
16998 opti++;
16999 if ("-a".equals(opt)) {
17000 dumpDetails = true;
17001 dumpFullDetails = true;
17002 dumpDalvik = true;
17003 dumpSwapPss = true;
17004 } else if ("-d".equals(opt)) {
17005 dumpDalvik = true;
17006 } else if ("-c".equals(opt)) {
17007 isCompact = true;
17008 } else if ("-s".equals(opt)) {
17009 dumpDetails = true;
17010 dumpSummaryOnly = true;
17011 } else if ("-S".equals(opt)) {
17012 dumpSwapPss = true;
17013 } else if ("--unreachable".equals(opt)) {
17014 dumpUnreachable = true;
17015 } else if ("--oom".equals(opt)) {
17016 oomOnly = true;
17017 } else if ("--local".equals(opt)) {
17018 localOnly = true;
17019 } else if ("--package".equals(opt)) {
17020 packages = true;
17021 } else if ("--checkin".equals(opt)) {
17022 isCheckinRequest = true;
17023
17024 } else if ("-h".equals(opt)) {
17025 pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]");
17026 pw.println(" -a: include all available information for each process.");
17027 pw.println(" -d: include dalvik details.");
17028 pw.println(" -c: dump in a compact machine-parseable representation.");
17029 pw.println(" -s: dump only summary of application memory usage.");
17030 pw.println(" -S: dump also SwapPss.");
17031 pw.println(" --oom: only show processes organized by oom adj.");
17032 pw.println(" --local: only collect details locally, don't call process.");
17033 pw.println(" --package: interpret process arg as package, dumping all");
17034 pw.println(" processes that have loaded that package.");
17035 pw.println(" --checkin: dump data for a checkin");
17036 pw.println("If [process] is specified it can be the name or ");
17037 pw.println("pid of a specific process to dump.");
17038 return;
17039 } else {
17040 pw.println("Unknown argument: " + opt + "; use -h for help");
17041 }
17042 }
17043
17044 long uptime = SystemClock.uptimeMillis();
17045 long realtime = SystemClock.elapsedRealtime();
17046 final long[] tmpLong = new long[1];
17047
17048 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, packages, args);
17049 if (procs == null) {
17050 // No Java processes. Maybe they want to print a native process.
17051 if (args != null && args.length > opti
17052 && args[opti].charAt(0) != '-') {
17053 ArrayList<ProcessCpuTracker.Stats> nativeProcs
17054 = new ArrayList<ProcessCpuTracker.Stats>();
17055 updateCpuStatsNow();
17056 int findPid = -1;
17057 try {
17058 findPid = Integer.parseInt(args[opti]);
17059 } catch (NumberFormatException e) {
17060 }
17061 synchronized (mProcessCpuTracker) {
17062 final int N = mProcessCpuTracker.countStats();
17063 for (int i=0; i<N; i++) {
17064 ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
17065 if (st.pid == findPid || (st.baseName != null
17066 && st.baseName.equals(args[opti]))) {
17067 nativeProcs.add(st);
17068 }
17069 }
17070 }
17071 if (nativeProcs.size() > 0) {
17072 dumpApplicationMemoryUsageHeader(pw, uptime, realtime, isCheckinRequest,
17073 isCompact);
17074 Debug.MemoryInfo mi = null;
17075 for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
17076 final ProcessCpuTracker.Stats r = nativeProcs.get(i);
17077 final int pid = r.pid;
17078 if (!isCheckinRequest && dumpDetails) {
17079 pw.println("\n** MEMINFO in pid " + pid + " [" + r.baseName + "] **");
17080 }
17081 if (mi == null) {
17082 mi = new Debug.MemoryInfo();
17083 }
17084 if (dumpDetails || (!brief && !oomOnly)) {
17085 Debug.getMemoryInfo(pid, mi);
17086 } else {
17087 mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
17088 mi.dalvikPrivateDirty = (int)tmpLong[0];
17089 }
17090 ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
17091 dumpDalvik, dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
17092 if (isCheckinRequest) {
17093 pw.println();
17094 }
17095 }
17096 return;
17097 }
17098 }
17099 pw.println("No process found for: " + args[opti]);
17100 return;
17101 }
17102
17103 if (!brief && !oomOnly && (procs.size() == 1 || isCheckinRequest || packages)) {
17104 dumpDetails = true;
17105 }
17106
17107 dumpApplicationMemoryUsageHeader(pw, uptime, realtime, isCheckinRequest, isCompact);
17108
17109 String[] innerArgs = new String[args.length-opti];
17110 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
17111
17112 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
17113 final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
17114 long nativePss = 0;
17115 long nativeSwapPss = 0;
17116 long dalvikPss = 0;
17117 long dalvikSwapPss = 0;
17118 long[] dalvikSubitemPss = dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
17119 EmptyArray.LONG;
17120 long[] dalvikSubitemSwapPss = dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
17121 EmptyArray.LONG;
17122 long otherPss = 0;
17123 long otherSwapPss = 0;
17124 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
17125 long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
17126
17127 long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
17128 long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length];
17129 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
17130 new ArrayList[DUMP_MEM_OOM_LABEL.length];
17131
17132 long totalPss = 0;
17133 long totalSwapPss = 0;
17134 long cachedPss = 0;
17135 long cachedSwapPss = 0;
17136 boolean hasSwapPss = false;
17137
17138 Debug.MemoryInfo mi = null;
17139 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
17140 final ProcessRecord r = procs.get(i);
17141 final IApplicationThread thread;
17142 final int pid;
17143 final int oomAdj;
17144 final boolean hasActivities;
17145 synchronized (this) {
17146 thread = r.thread;
17147 pid = r.pid;
17148 oomAdj = r.getSetAdjWithServices();
17149 hasActivities = r.activities.size() > 0;
17150 }
17151 if (thread != null) {
17152 if (!isCheckinRequest && dumpDetails) {
17153 pw.println("\n** MEMINFO in pid " + pid + " [" + r.processName + "] **");
17154 }
17155 if (mi == null) {
17156 mi = new Debug.MemoryInfo();
17157 }
17158 if (dumpDetails || (!brief && !oomOnly)) {
17159 Debug.getMemoryInfo(pid, mi);
17160 hasSwapPss = mi.hasSwappedOutPss;
17161 } else {
17162 mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
17163 mi.dalvikPrivateDirty = (int)tmpLong[0];
17164 }
17165 if (dumpDetails) {
17166 if (localOnly) {
17167 ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
17168 dumpDalvik, dumpSummaryOnly, pid, r.processName, 0, 0, 0, 0, 0, 0);
17169 if (isCheckinRequest) {
17170 pw.println();
17171 }
17172 } else {
17173 pw.flush();
17174 try {
17175 TransferPipe tp = new TransferPipe();
17176 try {
17177 thread.dumpMemInfo(tp.getWriteFd(),
17178 mi, isCheckinRequest, dumpFullDetails,
17179 dumpDalvik, dumpSummaryOnly, dumpUnreachable, innerArgs);
17180 tp.go(fd);
17181 } finally {
17182 tp.kill();
17183 }
17184 } catch (IOException e) {
17185 if (!isCheckinRequest) {
17186 pw.println("Got IoException!");
17187 pw.flush();
17188 }
17189 } catch (RemoteException e) {
17190 if (!isCheckinRequest) {
17191 pw.println("Got RemoteException!");
17192 pw.flush();
17193 }
17194 }
17195 }
17196 }
17197
17198 final long myTotalPss = mi.getTotalPss();
17199 final long myTotalUss = mi.getTotalUss();
17200 final long myTotalSwapPss = mi.getTotalSwappedOutPss();
17201
17202 synchronized (this) {
17203 if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
17204 // Record this for posterity if the process has been stable.
17205 r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true, r.pkgList);
17206 }
17207 }
17208
17209 if (!isCheckinRequest && mi != null) {
17210 totalPss += myTotalPss;
17211 totalSwapPss += myTotalSwapPss;
17212 MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
17213 (hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
17214 myTotalSwapPss, pid, hasActivities);
17215 procMems.add(pssItem);
17216 procMemsMap.put(pid, pssItem);
17217
17218 nativePss += mi.nativePss;
17219 nativeSwapPss += mi.nativeSwappedOutPss;
17220 dalvikPss += mi.dalvikPss;
17221 dalvikSwapPss += mi.dalvikSwappedOutPss;
17222 for (int j=0; j<dalvikSubitemPss.length; j++) {
17223 dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
17224 dalvikSubitemSwapPss[j] +=
17225 mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
17226 }
17227 otherPss += mi.otherPss;
17228 otherSwapPss += mi.otherSwappedOutPss;
17229 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
17230 long mem = mi.getOtherPss(j);
17231 miscPss[j] += mem;
17232 otherPss -= mem;
17233 mem = mi.getOtherSwappedOutPss(j);
17234 miscSwapPss[j] += mem;
17235 otherSwapPss -= mem;
17236 }
17237
17238 if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
17239 cachedPss += myTotalPss;
17240 cachedSwapPss += myTotalSwapPss;
17241 }
17242
17243 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
17244 if (oomIndex == (oomPss.length - 1)
17245 || (oomAdj >= DUMP_MEM_OOM_ADJ[oomIndex]
17246 && oomAdj < DUMP_MEM_OOM_ADJ[oomIndex + 1])) {
17247 oomPss[oomIndex] += myTotalPss;
17248 oomSwapPss[oomIndex] += myTotalSwapPss;
17249 if (oomProcs[oomIndex] == null) {
17250 oomProcs[oomIndex] = new ArrayList<MemItem>();
17251 }
17252 oomProcs[oomIndex].add(pssItem);
17253 break;
17254 }
17255 }
17256 }
17257 }
17258 }
17259
17260 long nativeProcTotalPss = 0;
17261
17262 if (!isCheckinRequest && procs.size() > 1 && !packages) {
17263 // If we are showing aggregations, also look for native processes to
17264 // include so that our aggregations are more accurate.
17265 updateCpuStatsNow();
17266 mi = null;
17267 synchronized (mProcessCpuTracker) {
17268 final int N = mProcessCpuTracker.countStats();
17269 for (int i=0; i<N; i++) {
17270 ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
17271 if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
17272 if (mi == null) {
17273 mi = new Debug.MemoryInfo();
17274 }
17275 if (!brief && !oomOnly) {
17276 Debug.getMemoryInfo(st.pid, mi);
17277 } else {
17278 mi.nativePss = (int)Debug.getPss(st.pid, tmpLong, null);
17279 mi.nativePrivateDirty = (int)tmpLong[0];
17280 }
17281
17282 final long myTotalPss = mi.getTotalPss();
17283 final long myTotalSwapPss = mi.getTotalSwappedOutPss();
17284 totalPss += myTotalPss;
17285 nativeProcTotalPss += myTotalPss;
17286
17287 MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
17288 st.name, myTotalPss, mi.getSummaryTotalSwapPss(), st.pid, false);
17289 procMems.add(pssItem);
17290
17291 nativePss += mi.nativePss;
17292 nativeSwapPss += mi.nativeSwappedOutPss;
17293 dalvikPss += mi.dalvikPss;
17294 dalvikSwapPss += mi.dalvikSwappedOutPss;
17295 for (int j=0; j<dalvikSubitemPss.length; j++) {
17296 dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
17297 dalvikSubitemSwapPss[j] +=
17298 mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
17299 }
17300 otherPss += mi.otherPss;
17301 otherSwapPss += mi.otherSwappedOutPss;
17302 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
17303 long mem = mi.getOtherPss(j);
17304 miscPss[j] += mem;
17305 otherPss -= mem;
17306 mem = mi.getOtherSwappedOutPss(j);
17307 miscSwapPss[j] += mem;
17308 otherSwapPss -= mem;
17309 }
17310 oomPss[0] += myTotalPss;
17311 oomSwapPss[0] += myTotalSwapPss;
17312 if (oomProcs[0] == null) {
17313 oomProcs[0] = new ArrayList<MemItem>();
17314 }
17315 oomProcs[0].add(pssItem);
17316 }
17317 }
17318 }
17319
17320 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
17321
17322 catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, -1));
17323 final MemItem dalvikItem =
17324 new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, -2);
17325 if (dalvikSubitemPss.length > 0) {
17326 dalvikItem.subitems = new ArrayList<MemItem>();
17327 for (int j=0; j<dalvikSubitemPss.length; j++) {
17328 final String name = Debug.MemoryInfo.getOtherLabel(
17329 Debug.MemoryInfo.NUM_OTHER_STATS + j);
17330 dalvikItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
17331 dalvikSubitemSwapPss[j], j));
17332 }
17333 }
17334 catMems.add(dalvikItem);
17335 catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, -3));
17336 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
17337 String label = Debug.MemoryInfo.getOtherLabel(j);
17338 catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], j));
17339 }
17340
17341 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
17342 for (int j=0; j<oomPss.length; j++) {
17343 if (oomPss[j] != 0) {
17344 String label = isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j]
17345 : DUMP_MEM_OOM_LABEL[j];
17346 MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j],
17347 DUMP_MEM_OOM_ADJ[j]);
17348 item.subitems = oomProcs[j];
17349 oomMems.add(item);
17350 }
17351 }
17352
17353 dumpSwapPss = dumpSwapPss && hasSwapPss && totalSwapPss != 0;
17354 if (!brief && !oomOnly && !isCompact) {
17355 pw.println();
17356 pw.println("Total PSS by process:");
17357 dumpMemItems(pw, " ", "proc", procMems, true, isCompact, dumpSwapPss);
17358 pw.println();
17359 }
17360 if (!isCompact) {
17361 pw.println("Total PSS by OOM adjustment:");
17362 }
17363 dumpMemItems(pw, " ", "oom", oomMems, false, isCompact, dumpSwapPss);
17364 if (!brief && !oomOnly) {
17365 PrintWriter out = categoryPw != null ? categoryPw : pw;
17366 if (!isCompact) {
17367 out.println();
17368 out.println("Total PSS by category:");
17369 }
17370 dumpMemItems(out, " ", "cat", catMems, true, isCompact, dumpSwapPss);
17371 }
17372 if (!isCompact) {
17373 pw.println();
17374 }
17375 MemInfoReader memInfo = new MemInfoReader();
17376 memInfo.readMemInfo();
17377 if (nativeProcTotalPss > 0) {
17378 synchronized (this) {
17379 final long cachedKb = memInfo.getCachedSizeKb();
17380 final long freeKb = memInfo.getFreeSizeKb();
17381 final long zramKb = memInfo.getZramTotalSizeKb();
17382 final long kernelKb = memInfo.getKernelUsedSizeKb();
17383 EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
17384 kernelKb*1024, nativeProcTotalPss*1024);
17385 mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
17386 nativeProcTotalPss);
17387 }
17388 }
17389 if (!brief) {
17390 if (!isCompact) {
17391 pw.print("Total RAM: "); pw.print(stringifyKBSize(memInfo.getTotalSizeKb()));
17392 pw.print(" (status ");
17393 switch (mLastMemoryLevel) {
17394 case ProcessStats.ADJ_MEM_FACTOR_NORMAL:
17395 pw.println("normal)");
17396 break;
17397 case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
17398 pw.println("moderate)");
17399 break;
17400 case ProcessStats.ADJ_MEM_FACTOR_LOW:
17401 pw.println("low)");
17402 break;
17403 case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
17404 pw.println("critical)");
17405 break;
17406 default:
17407 pw.print(mLastMemoryLevel);
17408 pw.println(")");
17409 break;
17410 }
17411 pw.print(" Free RAM: ");
17412 pw.print(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
17413 + memInfo.getFreeSizeKb()));
17414 pw.print(" (");
17415 pw.print(stringifyKBSize(cachedPss));
17416 pw.print(" cached pss + ");
17417 pw.print(stringifyKBSize(memInfo.getCachedSizeKb()));
17418 pw.print(" cached kernel + ");
17419 pw.print(stringifyKBSize(memInfo.getFreeSizeKb()));
17420 pw.println(" free)");
17421 } else {
17422 pw.print("ram,"); pw.print(memInfo.getTotalSizeKb()); pw.print(",");
17423 pw.print(cachedPss + memInfo.getCachedSizeKb()
17424 + memInfo.getFreeSizeKb()); pw.print(",");
17425 pw.println(totalPss - cachedPss);
17426 }
17427 }
17428 long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
17429 - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
17430 - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
17431 if (!isCompact) {
17432 pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
17433 + memInfo.getKernelUsedSizeKb())); pw.print(" (");
17434 pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + ");
17435 pw.print(stringifyKBSize(memInfo.getKernelUsedSizeKb())); pw.print(" kernel)\n");
17436 pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM));
17437 } else {
17438 pw.print("lostram,"); pw.println(lostRAM);
17439 }
17440 if (!brief) {
17441 if (memInfo.getZramTotalSizeKb() != 0) {
17442 if (!isCompact) {
17443 pw.print(" ZRAM: ");
17444 pw.print(stringifyKBSize(memInfo.getZramTotalSizeKb()));
17445 pw.print(" physical used for ");
17446 pw.print(stringifyKBSize(memInfo.getSwapTotalSizeKb()
17447 - memInfo.getSwapFreeSizeKb()));
17448 pw.print(" in swap (");
17449 pw.print(stringifyKBSize(memInfo.getSwapTotalSizeKb()));
17450 pw.println(" total swap)");
17451 } else {
17452 pw.print("zram,"); pw.print(memInfo.getZramTotalSizeKb()); pw.print(",");
17453 pw.print(memInfo.getSwapTotalSizeKb()); pw.print(",");
17454 pw.println(memInfo.getSwapFreeSizeKb());
17455 }
17456 }
17457 final long[] ksm = getKsmInfo();
17458 if (!isCompact) {
17459 if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
17460 || ksm[KSM_VOLATILE] != 0) {
17461 pw.print(" KSM: "); pw.print(stringifyKBSize(ksm[KSM_SHARING]));
17462 pw.print(" saved from shared ");
17463 pw.print(stringifyKBSize(ksm[KSM_SHARED]));
17464 pw.print(" "); pw.print(stringifyKBSize(ksm[KSM_UNSHARED]));
17465 pw.print(" unshared; ");
17466 pw.print(stringifyKBSize(
17467 ksm[KSM_VOLATILE])); pw.println(" volatile");
17468 }
17469 pw.print(" Tuning: ");
17470 pw.print(ActivityManager.staticGetMemoryClass());
17471 pw.print(" (large ");
17472 pw.print(ActivityManager.staticGetLargeMemoryClass());
17473 pw.print("), oom ");
17474 pw.print(stringifySize(
17475 mProcessList.getMemLevel(ProcessList.CACHED_APP_MAX_ADJ), 1024));
17476 pw.print(", restore limit ");
17477 pw.print(stringifyKBSize(mProcessList.getCachedRestoreThresholdKb()));
17478 if (ActivityManager.isLowRamDeviceStatic()) {
17479 pw.print(" (low-ram)");
17480 }
17481 if (ActivityManager.isHighEndGfx()) {
17482 pw.print(" (high-end-gfx)");
17483 }
17484 pw.println();
17485 } else {
17486 pw.print("ksm,"); pw.print(ksm[KSM_SHARING]); pw.print(",");
17487 pw.print(ksm[KSM_SHARED]); pw.print(","); pw.print(ksm[KSM_UNSHARED]);
17488 pw.print(","); pw.println(ksm[KSM_VOLATILE]);
17489 pw.print("tuning,");
17490 pw.print(ActivityManager.staticGetMemoryClass());
17491 pw.print(',');
17492 pw.print(ActivityManager.staticGetLargeMemoryClass());
17493 pw.print(',');
17494 pw.print(mProcessList.getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024);
17495 if (ActivityManager.isLowRamDeviceStatic()) {
17496 pw.print(",low-ram");
17497 }
17498 if (ActivityManager.isHighEndGfx()) {
17499 pw.print(",high-end-gfx");
17500 }
17501 pw.println();
17502 }
17503 }
17504 }
17505 }
17506
17507 private void appendBasicMemEntry(StringBuilder sb, int oomAdj, int procState, long pss,
17508 long memtrack, String name) {
17509 sb.append(" ");
17510 sb.append(ProcessList.makeOomAdjString(oomAdj));
17511 sb.append(' ');
17512 sb.append(ProcessList.makeProcStateString(procState));
17513 sb.append(' ');
17514 ProcessList.appendRamKb(sb, pss);
17515 sb.append(": ");
17516 sb.append(name);
17517 if (memtrack > 0) {
17518 sb.append(" (");
17519 sb.append(stringifyKBSize(memtrack));
17520 sb.append(" memtrack)");
17521 }
17522 }
17523
17524 private void appendMemInfo(StringBuilder sb, ProcessMemInfo mi) {
17525 appendBasicMemEntry(sb, mi.oomAdj, mi.procState, mi.pss, mi.memtrack, mi.name);
17526 sb.append(" (pid ");
17527 sb.append(mi.pid);
17528 sb.append(") ");
17529 sb.append(mi.adjType);
17530 sb.append('\n');
17531 if (mi.adjReason != null) {
17532 sb.append(" ");
17533 sb.append(mi.adjReason);
17534 sb.append('\n');
17535 }
17536 }
17537
17538 void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) {
17539 final SparseArray<ProcessMemInfo> infoMap = new SparseArray<>(memInfos.size());
17540 for (int i=0, N=memInfos.size(); i<N; i++) {
17541 ProcessMemInfo mi = memInfos.get(i);
17542 infoMap.put(mi.pid, mi);
17543 }
17544 updateCpuStatsNow();
17545 long[] memtrackTmp = new long[1];
17546 final List<ProcessCpuTracker.Stats> stats;
17547 // Get a list of Stats that have vsize > 0
17548 synchronized (mProcessCpuTracker) {
17549 stats = mProcessCpuTracker.getStats((st) -> {
17550 return st.vsize > 0;
17551 });
17552 }
17553 final int statsCount = stats.size();
17554 for (int i = 0; i < statsCount; i++) {
17555 ProcessCpuTracker.Stats st = stats.get(i);
17556 long pss = Debug.getPss(st.pid, null, memtrackTmp);
17557 if (pss > 0) {
17558 if (infoMap.indexOfKey(st.pid) < 0) {
17559 ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
17560 ProcessList.NATIVE_ADJ, -1, "native", null);
17561 mi.pss = pss;
17562 mi.memtrack = memtrackTmp[0];
17563 memInfos.add(mi);
17564 }
17565 }
17566 }
17567
17568 long totalPss = 0;
17569 long totalMemtrack = 0;
17570 for (int i=0, N=memInfos.size(); i<N; i++) {
17571 ProcessMemInfo mi = memInfos.get(i);
17572 if (mi.pss == 0) {
17573 mi.pss = Debug.getPss(mi.pid, null, memtrackTmp);
17574 mi.memtrack = memtrackTmp[0];
17575 }
17576 totalPss += mi.pss;
17577 totalMemtrack += mi.memtrack;
17578 }
17579 Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
17580 @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
17581 if (lhs.oomAdj != rhs.oomAdj) {
17582 return lhs.oomAdj < rhs.oomAdj ? -1 : 1;
17583 }
17584 if (lhs.pss != rhs.pss) {
17585 return lhs.pss < rhs.pss ? 1 : -1;
17586 }
17587 return 0;
17588 }
17589 });
17590
17591 StringBuilder tag = new StringBuilder(128);
17592 StringBuilder stack = new StringBuilder(128);
17593 tag.append("Low on memory -- ");
17594 appendMemBucket(tag, totalPss, "total", false);
17595 appendMemBucket(stack, totalPss, "total", true);
17596
17597 StringBuilder fullNativeBuilder = new StringBuilder(1024);
17598 StringBuilder shortNativeBuilder = new StringBuilder(1024);
17599 StringBuilder fullJavaBuilder = new StringBuilder(1024);
17600
17601 boolean firstLine = true;
17602 int lastOomAdj = Integer.MIN_VALUE;
17603 long extraNativeRam = 0;
17604 long extraNativeMemtrack = 0;
17605 long cachedPss = 0;
17606 for (int i=0, N=memInfos.size(); i<N; i++) {
17607 ProcessMemInfo mi = memInfos.get(i);
17608
17609 if (mi.oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
17610 cachedPss += mi.pss;
17611 }
17612
17613 if (mi.oomAdj != ProcessList.NATIVE_ADJ
17614 && (mi.oomAdj < ProcessList.SERVICE_ADJ
17615 || mi.oomAdj == ProcessList.HOME_APP_ADJ
17616 || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) {
17617 if (lastOomAdj != mi.oomAdj) {
17618 lastOomAdj = mi.oomAdj;
17619 if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
17620 tag.append(" / ");
17621 }
17622 if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) {
17623 if (firstLine) {
17624 stack.append(":");
17625 firstLine = false;
17626 }
17627 stack.append("\n\t at ");
17628 } else {
17629 stack.append("$");
17630 }
17631 } else {
17632 tag.append(" ");
17633 stack.append("$");
17634 }
17635 if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
17636 appendMemBucket(tag, mi.pss, mi.name, false);
17637 }
17638 appendMemBucket(stack, mi.pss, mi.name, true);
17639 if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ
17640 && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) {
17641 stack.append("(");
17642 for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
17643 if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) {
17644 stack.append(DUMP_MEM_OOM_LABEL[k]);
17645 stack.append(":");
17646 stack.append(DUMP_MEM_OOM_ADJ[k]);
17647 }
17648 }
17649 stack.append(")");
17650 }
17651 }
17652
17653 appendMemInfo(fullNativeBuilder, mi);
17654 if (mi.oomAdj == ProcessList.NATIVE_ADJ) {
17655 // The short form only has native processes that are >= 512K.
17656 if (mi.pss >= 512) {
17657 appendMemInfo(shortNativeBuilder, mi);
17658 } else {
17659 extraNativeRam += mi.pss;
17660 extraNativeMemtrack += mi.memtrack;
17661 }
17662 } else {
17663 // Short form has all other details, but if we have collected RAM
17664 // from smaller native processes let's dump a summary of that.
17665 if (extraNativeRam > 0) {
17666 appendBasicMemEntry(shortNativeBuilder, ProcessList.NATIVE_ADJ,
17667 -1, extraNativeRam, extraNativeMemtrack, "(Other native)");
17668 shortNativeBuilder.append('\n');
17669 extraNativeRam = 0;
17670 }
17671 appendMemInfo(fullJavaBuilder, mi);
17672 }
17673 }
17674
17675 fullJavaBuilder.append(" ");
17676 ProcessList.appendRamKb(fullJavaBuilder, totalPss);
17677 fullJavaBuilder.append(": TOTAL");
17678 if (totalMemtrack > 0) {
17679 fullJavaBuilder.append(" (");
17680 fullJavaBuilder.append(stringifyKBSize(totalMemtrack));
17681 fullJavaBuilder.append(" memtrack)");
17682 } else {
17683 }
17684 fullJavaBuilder.append("\n");
17685
17686 MemInfoReader memInfo = new MemInfoReader();
17687 memInfo.readMemInfo();
17688 final long[] infos = memInfo.getRawInfo();
17689
17690 StringBuilder memInfoBuilder = new StringBuilder(1024);
17691 Debug.getMemInfo(infos);
17692 memInfoBuilder.append(" MemInfo: ");
17693 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SLAB])).append(" slab, ");
17694 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SHMEM])).append(" shmem, ");
17695 memInfoBuilder.append(stringifyKBSize(
17696 infos[Debug.MEMINFO_VM_ALLOC_USED])).append(" vm alloc, ");
17697 memInfoBuilder.append(stringifyKBSize(
17698 infos[Debug.MEMINFO_PAGE_TABLES])).append(" page tables ");
17699 memInfoBuilder.append(stringifyKBSize(
17700 infos[Debug.MEMINFO_KERNEL_STACK])).append(" kernel stack\n");
17701 memInfoBuilder.append(" ");
17702 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_BUFFERS])).append(" buffers, ");
17703 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_CACHED])).append(" cached, ");
17704 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_MAPPED])).append(" mapped, ");
17705 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_FREE])).append(" free\n");
17706 if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) {
17707 memInfoBuilder.append(" ZRAM: ");
17708 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_ZRAM_TOTAL]));
17709 memInfoBuilder.append(" RAM, ");
17710 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_TOTAL]));
17711 memInfoBuilder.append(" swap total, ");
17712 memInfoBuilder.append(stringifyKBSize(infos[Debug.MEMINFO_SWAP_FREE]));
17713 memInfoBuilder.append(" swap free\n");
17714 }
17715 final long[] ksm = getKsmInfo();
17716 if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
17717 || ksm[KSM_VOLATILE] != 0) {
17718 memInfoBuilder.append(" KSM: ");
17719 memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARING]));
17720 memInfoBuilder.append(" saved from shared ");
17721 memInfoBuilder.append(stringifyKBSize(ksm[KSM_SHARED]));
17722 memInfoBuilder.append("\n ");
17723 memInfoBuilder.append(stringifyKBSize(ksm[KSM_UNSHARED]));
17724 memInfoBuilder.append(" unshared; ");
17725 memInfoBuilder.append(stringifyKBSize(ksm[KSM_VOLATILE]));
17726 memInfoBuilder.append(" volatile\n");
17727 }
17728 memInfoBuilder.append(" Free RAM: ");
17729 memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
17730 + memInfo.getFreeSizeKb()));
17731 memInfoBuilder.append("\n");
17732 memInfoBuilder.append(" Used RAM: ");
17733 memInfoBuilder.append(stringifyKBSize(
17734 totalPss - cachedPss + memInfo.getKernelUsedSizeKb()));
17735 memInfoBuilder.append("\n");
17736 memInfoBuilder.append(" Lost RAM: ");
17737 memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
17738 - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
17739 - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()));
17740 memInfoBuilder.append("\n");
17741 Slog.i(TAG, "Low on memory:");
17742 Slog.i(TAG, shortNativeBuilder.toString());
17743 Slog.i(TAG, fullJavaBuilder.toString());
17744 Slog.i(TAG, memInfoBuilder.toString());
17745
17746 StringBuilder dropBuilder = new StringBuilder(1024);
17747 /*
17748 StringWriter oomSw = new StringWriter();
17749 PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
17750 StringWriter catSw = new StringWriter();
17751 PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
17752 String[] emptyArgs = new String[] { };
17753 dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw);
17754 oomPw.flush();
17755 String oomString = oomSw.toString();
17756 */
17757 dropBuilder.append("Low on memory:");
17758 dropBuilder.append(stack);
17759 dropBuilder.append('\n');
17760 dropBuilder.append(fullNativeBuilder);
17761 dropBuilder.append(fullJavaBuilder);
17762 dropBuilder.append('\n');
17763 dropBuilder.append(memInfoBuilder);
17764 dropBuilder.append('\n');
17765 /*
17766 dropBuilder.append(oomString);
17767 dropBuilder.append('\n');
17768 */
17769 StringWriter catSw = new StringWriter();
17770 synchronized (ActivityManagerService.this) {
17771 PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
17772 String[] emptyArgs = new String[] { };
17773 catPw.println();
17774 dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
17775 catPw.println();
17776 mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0,
17777 false, null).dumpLocked();
17778 catPw.println();
17779 dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
17780 catPw.flush();
17781 }
17782 dropBuilder.append(catSw.toString());
17783 addErrorToDropBox("lowmem", null, "system_server", null,
17784 null, tag.toString(), dropBuilder.toString(), null, null);
17785 //Slog.i(TAG, "Sent to dropbox:");
17786 //Slog.i(TAG, dropBuilder.toString());
17787 synchronized (ActivityManagerService.this) {
17788 long now = SystemClock.uptimeMillis();
17789 if (mLastMemUsageReportTime < now) {
17790 mLastMemUsageReportTime = now;
17791 }
17792 }
17793 }

扫描args

 17795    /**
17796 * Searches array of arguments for the specified string
17797 * @param args array of argument strings
17798 * @param value value to search for
17799 * @return true if the value is contained in the array
17800 */
17801 private static boolean scanArgs(String[] args, String value) {
17802 if (args != null) {
17803 for (String arg : args) {
17804 if (value.equals(arg)) {
17805 return true;
17806 }
17807 }
17808 }
17809 return false;
17810 }

移除正在死亡的provider

 17812    private final boolean removeDyingProviderLocked(ProcessRecord proc,
17813 ContentProviderRecord cpr, boolean always) {
17814 final boolean inLaunching = mLaunchingProviders.contains(cpr);
17815
17816 if (!inLaunching || always) {
17817 synchronized (cpr) {
17818 cpr.launchingApp = null;
17819 cpr.notifyAll();
17820 }
17821 mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
17822 String names[] = cpr.info.authority.split(";");
17823 for (int j = 0; j < names.length; j++) {
17824 mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
17825 }
17826 }
17827
17828 for (int i = cpr.connections.size() - 1; i >= 0; i--) {
17829 ContentProviderConnection conn = cpr.connections.get(i);
17830 if (conn.waiting) {
17831 // If this connection is waiting for the provider, then we don't
17832 // need to mess with its process unless we are always removing
17833 // or for some reason the provider is not currently launching.
17834 if (inLaunching && !always) {
17835 continue;
17836 }
17837 }
17838 ProcessRecord capp = conn.client;
17839 conn.dead = true;
17840 if (conn.stableCount > 0) {
17841 if (!capp.persistent && capp.thread != null
17842 && capp.pid != 0
17843 && capp.pid != MY_PID) {
17844 capp.kill("depends on provider "
17845 + cpr.name.flattenToShortString()
17846 + " in dying proc " + (proc != null ? proc.processName : "??")
17847 + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
17848 }
17849 } else if (capp.thread != null && conn.provider.provider != null) {
17850 try {
17851 capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
17852 } catch (RemoteException e) {
17853 }
17854 // In the protocol here, we don't expect the client to correctly
17855 // clean up this connection, we'll just remove it.
17856 cpr.connections.remove(i);
17857 if (conn.client.conProviders.remove(conn)) {
17858 stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
17859 }
17860 }
17861 }
17862
17863 if (inLaunching && always) {
17864 mLaunchingProviders.remove(cpr);
17865 }
17866 return inLaunching;
17867 }

清除应用程序记录

 17869    /**
17870 * Main code for cleaning up a process when it has gone away. This is
17871 * called both as a result of the process dying, or directly when stopping
17872 * a process when running in single process mode.
17873 *
17874 * @return Returns true if the given process has been restarted, so the
17875 * app that was passed in must remain on the process lists.
17876 */
17877 private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
17878 boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
17879 if (index >= 0) {
17880 removeLruProcessLocked(app);
17881 ProcessList.remove(app.pid);
17882 }
17883
17884 mProcessesToGc.remove(app);
17885 mPendingPssProcesses.remove(app);
17886
17887 // Dismiss any open dialogs.
17888 if (app.crashDialog != null && !app.forceCrashReport) {
17889 app.crashDialog.dismiss();
17890 app.crashDialog = null;
17891 }
17892 if (app.anrDialog != null) {
17893 app.anrDialog.dismiss();
17894 app.anrDialog = null;
17895 }
17896 if (app.waitDialog != null) {
17897 app.waitDialog.dismiss();
17898 app.waitDialog = null;
17899 }
17900
17901 app.crashing = false;
17902 app.notResponding = false;
17903
17904 app.resetPackageList(mProcessStats);
17905 app.unlinkDeathRecipient();
17906 app.makeInactive(mProcessStats);
17907 app.waitingToKill = null;
17908 app.forcingToImportant = null;
17909 updateProcessForegroundLocked(app, false, false);
17910 app.foregroundActivities = false;
17911 app.hasShownUi = false;
17912 app.treatLikeActivity = false;
17913 app.hasAboveClient = false;
17914 app.hasClientActivities = false;
17915
17916 mServices.killServicesLocked(app, allowRestart);
17917
17918 boolean restart = false;
17919
17920 // Remove published content providers.
17921 for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
17922 ContentProviderRecord cpr = app.pubProviders.valueAt(i);
17923 final boolean always = app.bad || !allowRestart;
17924 boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
17925 if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
17926 // We left the provider in the launching list, need to
17927 // restart it.
17928 restart = true;
17929 }
17930
17931 cpr.provider = null;
17932 cpr.proc = null;
17933 }
17934 app.pubProviders.clear();
17935
17936 // Take care of any launching providers waiting for this process.
17937 if (cleanupAppInLaunchingProvidersLocked(app, false)) {
17938 restart = true;
17939 }
17940
17941 // Unregister from connected content providers.
17942 if (!app.conProviders.isEmpty()) {
17943 for (int i = app.conProviders.size() - 1; i >= 0; i--) {
17944 ContentProviderConnection conn = app.conProviders.get(i);
17945 conn.provider.connections.remove(conn);
17946 stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
17947 conn.provider.name);
17948 }
17949 app.conProviders.clear();
17950 }
17951
17952 // At this point there may be remaining entries in mLaunchingProviders
17953 // where we were the only one waiting, so they are no longer of use.
17954 // Look for these and clean up if found.
17955 // XXX Commented out for now. Trying to figure out a way to reproduce
17956 // the actual situation to identify what is actually going on.
17957 if (false) {
17958 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
17959 ContentProviderRecord cpr = mLaunchingProviders.get(i);
17960 if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
17961 synchronized (cpr) {
17962 cpr.launchingApp = null;
17963 cpr.notifyAll();
17964 }
17965 }
17966 }
17967 }
17968
17969 skipCurrentReceiverLocked(app);
17970
17971 // Unregister any receivers.
17972 for (int i = app.receivers.size() - 1; i >= 0; i--) {
17973 removeReceiverLocked(app.receivers.valueAt(i));
17974 }
17975 app.receivers.clear();
17976
17977 // If the app is undergoing backup, tell the backup manager about it
17978 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
17979 if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
17980 + mBackupTarget.appInfo + " died during backup");
17981 mHandler.post(new Runnable() {
17982 @Override
17983 public void run(){
17984 try {
17985 IBackupManager bm = IBackupManager.Stub.asInterface(
17986 ServiceManager.getService(Context.BACKUP_SERVICE));
17987 bm.agentDisconnected(app.info.packageName);
17988 } catch (RemoteException e) {
17989 // can't happen; backup manager is local
17990 }
17991 }
17992 });
17993 }
17994
17995 for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
17996 ProcessChangeItem item = mPendingProcessChanges.get(i);
17997 if (item.pid == app.pid) {
17998 mPendingProcessChanges.remove(i);
17999 mAvailProcessChanges.add(item);
18000 }
18001 }
18002 mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid,
18003 null).sendToTarget();
18004
18005 // If the caller is restarting this app, then leave it in its
18006 // current lists and let the caller take care of it.
18007 if (restarting) {
18008 return false;
18009 }
18010
18011 if (!app.persistent || app.isolated) {
18012 if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
18013 "Removing non-persistent process during cleanup: " + app);
18014 if (!replacingPid) {
18015 removeProcessNameLocked(app.processName, app.uid, app);
18016 }
18017 if (mHeavyWeightProcess == app) {
18018 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
18019 mHeavyWeightProcess.userId, 0));
18020 mHeavyWeightProcess = null;
18021 }
18022 } else if (!app.removed) {
18023 // This app is persistent, so we need to keep its record around.
18024 // If it is not already on the pending app list, add it there
18025 // and start a new process for it.
18026 if (mPersistentStartingProcesses.indexOf(app) < 0) {
18027 mPersistentStartingProcesses.add(app);
18028 restart = true;
18029 }
18030 }
18031 if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
18032 TAG_CLEANUP, "Clean-up removing on hold: " + app);
18033 mProcessesOnHold.remove(app);
18034
18035 if (app == mHomeProcess) {
18036 mHomeProcess = null;
18037 }
18038 if (app == mPreviousProcess) {
18039 mPreviousProcess = null;
18040 }
18041
18042 if (restart && !app.isolated) {
18043 // We have components that still need to be running in the
18044 // process, so re-launch it.
18045 if (index < 0) {
18046 ProcessList.remove(app.pid);
18047 }
18048 addProcessNameLocked(app);
18049 startProcessLocked(app, "restart", app.processName);
18050 return true;
18051 } else if (app.pid > 0 && app.pid != MY_PID) {
18052 // Goodbye!
18053 boolean removed;
18054 synchronized (mPidsSelfLocked) {
18055 mPidsSelfLocked.remove(app.pid);
18056 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
18057 }
18058 mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
18059 if (app.isolated) {
18060 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
18061 }
18062 app.setPid(0);
18063 }
18064 return false;
18065 }

检查与清除app启动时的provider

 18067    boolean checkAppInLaunchingProvidersLocked(ProcessRecord app) {
18068 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
18069 ContentProviderRecord cpr = mLaunchingProviders.get(i);
18070 if (cpr.launchingApp == app) {
18071 return true;
18072 }
18073 }
18074 return false;
18075 }
18076
18077 boolean cleanupAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
18078 // Look through the content providers we are waiting to have launched,
18079 // and if any run in this process then either schedule a restart of
18080 // the process or kill the client waiting for it if this process has
18081 // gone bad.
18082 boolean restart = false;
18083 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
18084 ContentProviderRecord cpr = mLaunchingProviders.get(i);
18085 if (cpr.launchingApp == app) {
18086 if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
18087 restart = true;
18088 } else {
18089 removeDyingProviderLocked(app, cpr, true);
18090 }
18091 }
18092 }
18093 return restart;
18094 }

service相关

 18095
18096 // =========================================================
18097 // SERVICES
18098 // =========================================================
18099
18100 @Override
18101 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
18102 int flags) {
18103 enforceNotIsolatedCaller("getServices");
18104
18105 final int callingUid = Binder.getCallingUid();
18106 final boolean canInteractAcrossUsers = (ActivityManager.checkUidPermission(
18107 INTERACT_ACROSS_USERS_FULL, callingUid) == PERMISSION_GRANTED);
18108 final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
18109 callingUid);
18110 synchronized (this) {
18111 return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid,
18112 allowed, canInteractAcrossUsers);
18113 }
18114 }
18115
18116 @Override
18117 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
18118 enforceNotIsolatedCaller("getRunningServiceControlPanel");
18119 synchronized (this) {
18120 return mServices.getRunningServiceControlPanelLocked(name);
18121 }
18122 }
18123
18124 @Override
18125 public ComponentName startService(IApplicationThread caller, Intent service,
18126 String resolvedType, boolean requireForeground, String callingPackage, int userId)
18127 throws TransactionTooLargeException {
18128 enforceNotIsolatedCaller("startService");
18129 // Refuse possible leaked file descriptors
18130 if (service != null && service.hasFileDescriptors() == true) {
18131 throw new IllegalArgumentException("File descriptors passed in Intent");
18132 }
18133
18134 if (callingPackage == null) {
18135 throw new IllegalArgumentException("callingPackage cannot be null");
18136 }
18137
18138 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
18139 "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
18140 synchronized(this) {
18141 final int callingPid = Binder.getCallingPid();
18142 final int callingUid = Binder.getCallingUid();
18143 final long origId = Binder.clearCallingIdentity();
18144 ComponentName res;
18145 try {
18146 res = mServices.startServiceLocked(caller, service,
18147 resolvedType, callingPid, callingUid,
18148 requireForeground, callingPackage, userId);
18149 } finally {
18150 Binder.restoreCallingIdentity(origId);
18151 }
18152 return res;
18153 }
18154 }
18155
18156 ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
18157 boolean fgRequired, String callingPackage, int userId)
18158 throws TransactionTooLargeException {
18159 synchronized(this) {
18160 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
18161 "startServiceInPackage: " + service + " type=" + resolvedType);
18162 final long origId = Binder.clearCallingIdentity();
18163 ComponentName res;
18164 try {
18165 res = mServices.startServiceLocked(null, service,
18166 resolvedType, -1, uid, fgRequired, callingPackage, userId);
18167 } finally {
18168 Binder.restoreCallingIdentity(origId);
18169 }
18170 return res;
18171 }
18172 }
18173
18174 @Override
18175 public int stopService(IApplicationThread caller, Intent service,
18176 String resolvedType, int userId) {
18177 enforceNotIsolatedCaller("stopService");
18178 // Refuse possible leaked file descriptors
18179 if (service != null && service.hasFileDescriptors() == true) {
18180 throw new IllegalArgumentException("File descriptors passed in Intent");
18181 }
18182
18183 synchronized(this) {
18184 return mServices.stopServiceLocked(caller, service, resolvedType, userId);
18185 }
18186 }
18187
18188 @Override
18189 public IBinder peekService(Intent service, String resolvedType, String callingPackage) {
18190 enforceNotIsolatedCaller("peekService");
18191 // Refuse possible leaked file descriptors
18192 if (service != null && service.hasFileDescriptors() == true) {
18193 throw new IllegalArgumentException("File descriptors passed in Intent");
18194 }
18195
18196 if (callingPackage == null) {
18197 throw new IllegalArgumentException("callingPackage cannot be null");
18198 }
18199
18200 synchronized(this) {
18201 return mServices.peekServiceLocked(service, resolvedType, callingPackage);
18202 }
18203 }
18204
18205 @Override
18206 public boolean stopServiceToken(ComponentName className, IBinder token,
18207 int startId) {
18208 synchronized(this) {
18209 return mServices.stopServiceTokenLocked(className, token, startId);
18210 }
18211 }
18212
18213 @Override
18214 public void setServiceForeground(ComponentName className, IBinder token,
18215 int id, Notification notification, int flags) {
18216 synchronized(this) {
18217 mServices.setServiceForegroundLocked(className, token, id, notification, flags);
18218 }
18219 }
18220
18221 @Override
18222 public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
18223 boolean requireFull, String name, String callerPackage) {
18224 return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
18225 requireFull ? ALLOW_FULL_ONLY : ALLOW_NON_FULL, name, callerPackage);
18226 }
18227
18228 boolean isSingleton(String componentProcessName, ApplicationInfo aInfo,
18229 String className, int flags) {
18230 boolean result = false;
18231 // For apps that don't have pre-defined UIDs, check for permission
18232 if (UserHandle.getAppId(aInfo.uid) >= FIRST_APPLICATION_UID) {
18233 if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
18234 if (ActivityManager.checkUidPermission(
18235 INTERACT_ACROSS_USERS,
18236 aInfo.uid) != PackageManager.PERMISSION_GRANTED) {
18237 ComponentName comp = new ComponentName(aInfo.packageName, className);
18238 String msg = "Permission Denial: Component " + comp.flattenToShortString()
18239 + " requests FLAG_SINGLE_USER, but app does not hold "
18240 + INTERACT_ACROSS_USERS;
18241 Slog.w(TAG, msg);
18242 throw new SecurityException(msg);
18243 }
18244 // Permission passed
18245 result = true;
18246 }
18247 } else if ("system".equals(componentProcessName)) {
18248 result = true;
18249 } else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
18250 // Phone app and persistent apps are allowed to export singleuser providers.
18251 result = UserHandle.isSameApp(aInfo.uid, PHONE_UID)
18252 || (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
18253 }
18254 if (DEBUG_MU) Slog.v(TAG_MU,
18255 "isSingleton(" + componentProcessName + ", " + aInfo + ", " + className + ", 0x"
18256 + Integer.toHexString(flags) + ") = " + result);
18257 return result;
18258 }
18259
18260 /**
18261 * Checks to see if the caller is in the same app as the singleton
18262 * component, or the component is in a special app. It allows special apps
18263 * to export singleton components but prevents exporting singleton
18264 * components for regular apps.
18265 */
18266 boolean isValidSingletonCall(int callingUid, int componentUid) {
18267 int componentAppId = UserHandle.getAppId(componentUid);
18268 return UserHandle.isSameApp(callingUid, componentUid)
18269 || componentAppId == SYSTEM_UID
18270 || componentAppId == PHONE_UID
18271 || ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, componentUid)
18272 == PackageManager.PERMISSION_GRANTED;
18273 }
18274
18275 public int bindService(IApplicationThread caller, IBinder token, Intent service,
18276 String resolvedType, IServiceConnection connection, int flags, String callingPackage,
18277 int userId) throws TransactionTooLargeException {
18278 enforceNotIsolatedCaller("bindService");
18279
18280 // Refuse possible leaked file descriptors
18281 if (service != null && service.hasFileDescriptors() == true) {
18282 throw new IllegalArgumentException("File descriptors passed in Intent");
18283 }
18284
18285 if (callingPackage == null) {
18286 throw new IllegalArgumentException("callingPackage cannot be null");
18287 }
18288
18289 synchronized(this) {
18290 return mServices.bindServiceLocked(caller, token, service,
18291 resolvedType, connection, flags, callingPackage, userId);
18292 }
18293 }
18294
18295 public boolean unbindService(IServiceConnection connection) {
18296 synchronized (this) {
18297 return mServices.unbindServiceLocked(connection);
18298 }
18299 }
18300
18301 public void publishService(IBinder token, Intent intent, IBinder service) {
18302 // Refuse possible leaked file descriptors
18303 if (intent != null && intent.hasFileDescriptors() == true) {
18304 throw new IllegalArgumentException("File descriptors passed in Intent");
18305 }
18306
18307 synchronized(this) {
18308 if (!(token instanceof ServiceRecord)) {
18309 throw new IllegalArgumentException("Invalid service token");
18310 }
18311 mServices.publishServiceLocked((ServiceRecord)token, intent, service);
18312 }
18313 }
18314
18315 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
18316 // Refuse possible leaked file descriptors
18317 if (intent != null && intent.hasFileDescriptors() == true) {
18318 throw new IllegalArgumentException("File descriptors passed in Intent");
18319 }
18320
18321 synchronized(this) {
18322 mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind);
18323 }
18324 }
18325
18326 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
18327 synchronized(this) {
18328 if (!(token instanceof ServiceRecord)) {
18329 Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
18330 throw new IllegalArgumentException("Invalid service token");
18331 }
18332 mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
18333 }
18334 }

备份和恢复

 18336    // =========================================================
18337 // BACKUP AND RESTORE
18338 // =========================================================
18339
18340 // Cause the target app to be launched if necessary and its backup agent
18341 // instantiated. The backup agent will invoke backupAgentCreated() on the
18342 // activity manager to announce its creation.
18343 public boolean bindBackupAgent(String packageName, int backupMode, int userId) {
18344 if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode);
18345 enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent");
18346
18347 IPackageManager pm = AppGlobals.getPackageManager();
18348 ApplicationInfo app = null;
18349 try {
18350 app = pm.getApplicationInfo(packageName, 0, userId);
18351 } catch (RemoteException e) {
18352 // can't happen; package manager is process-local
18353 }
18354 if (app == null) {
18355 Slog.w(TAG, "Unable to bind backup agent for " + packageName);
18356 return false;
18357 }
18358
18359 int oldBackupUid;
18360 int newBackupUid;
18361
18362 synchronized(this) {
18363 // !!! TODO: currently no check here that we're already bound
18364 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
18365 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
18366 synchronized (stats) {
18367 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
18368 }
18369
18370 // Backup agent is now in use, its package can't be stopped.
18371 try {
18372 AppGlobals.getPackageManager().setPackageStoppedState(
18373 app.packageName, false, UserHandle.getUserId(app.uid));
18374 } catch (RemoteException e) {
18375 } catch (IllegalArgumentException e) {
18376 Slog.w(TAG, "Failed trying to unstop package "
18377 + app.packageName + ": " + e);
18378 }
18379
18380 BackupRecord r = new BackupRecord(ss, app, backupMode);
18381 ComponentName hostingName =
18382 (backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL)
18383 ? new ComponentName(app.packageName, app.backupAgentName)
18384 : new ComponentName("android", "FullBackupAgent");
18385 // startProcessLocked() returns existing proc's record if it's already running
18386 ProcessRecord proc = startProcessLocked(app.processName, app,
18387 false, 0, "backup", hostingName, false, false, false);
18388 if (proc == null) {
18389 Slog.e(TAG, "Unable to start backup agent process " + r);
18390 return false;
18391 }
18392
18393 // If the app is a regular app (uid >= 10000) and not the system server or phone
18394 // process, etc, then mark it as being in full backup so that certain calls to the
18395 // process can be blocked. This is not reset to false anywhere because we kill the
18396 // process after the full backup is done and the ProcessRecord will vaporize anyway.
18397 if (UserHandle.isApp(app.uid) &&
18398 backupMode == ApplicationThreadConstants.BACKUP_MODE_FULL) {
18399 proc.inFullBackup = true;
18400 }
18401 r.app = proc;
18402 oldBackupUid = mBackupTarget != null ? mBackupTarget.appInfo.uid : -1;
18403 newBackupUid = proc.inFullBackup ? r.appInfo.uid : -1;
18404 mBackupTarget = r;
18405 mBackupAppName = app.packageName;
18406
18407 // Try not to kill the process during backup
18408 updateOomAdjLocked(proc, true);
18409
18410 // If the process is already attached, schedule the creation of the backup agent now.
18411 // If it is not yet live, this will be done when it attaches to the framework.
18412 if (proc.thread != null) {
18413 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "Agent proc already running: " + proc);
18414 try {
18415 proc.thread.scheduleCreateBackupAgent(app,
18416 compatibilityInfoForPackageLocked(app), backupMode);
18417 } catch (RemoteException e) {
18418 // Will time out on the backup manager side
18419 }
18420 } else {
18421 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "Agent proc not running, waiting for attach");
18422 }
18423 // Invariants: at this point, the target app process exists and the application
18424 // is either already running or in the process of coming up. mBackupTarget and
18425 // mBackupAppName describe the app, so that when it binds back to the AM we
18426 // know that it's scheduled for a backup-agent operation.
18427 }
18428
18429 JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
18430 if (oldBackupUid != -1) {
18431 js.removeBackingUpUid(oldBackupUid);
18432 }
18433 if (newBackupUid != -1) {
18434 js.addBackingUpUid(newBackupUid);
18435 }
18436
18437 return true;
18438 }
18439
18440 @Override
18441 public void clearPendingBackup() {
18442 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "clearPendingBackup");
18443 enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup");
18444
18445 synchronized (this) {
18446 mBackupTarget = null;
18447 mBackupAppName = null;
18448 }
18449
18450 JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
18451 js.clearAllBackingUpUids();
18452 }
18453
18454 // A backup agent has just come up
18455 public void backupAgentCreated(String agentPackageName, IBinder agent) {
18456 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName
18457 + " = " + agent);
18458
18459 synchronized(this) {
18460 if (!agentPackageName.equals(mBackupAppName)) {
18461 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
18462 return;
18463 }
18464 }
18465
18466 long oldIdent = Binder.clearCallingIdentity();
18467 try {
18468 IBackupManager bm = IBackupManager.Stub.asInterface(
18469 ServiceManager.getService(Context.BACKUP_SERVICE));
18470 bm.agentConnected(agentPackageName, agent);
18471 } catch (RemoteException e) {
18472 // can't happen; the backup manager service is local
18473 } catch (Exception e) {
18474 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
18475 e.printStackTrace();
18476 } finally {
18477 Binder.restoreCallingIdentity(oldIdent);
18478 }
18479 }
18480
18481 // done with this agent
18482 public void unbindBackupAgent(ApplicationInfo appInfo) {
18483 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "unbindBackupAgent: " + appInfo);
18484 if (appInfo == null) {
18485 Slog.w(TAG, "unbind backup agent for null app");
18486 return;
18487 }
18488
18489 int oldBackupUid;
18490
18491 synchronized(this) {
18492 try {
18493 if (mBackupAppName == null) {
18494 Slog.w(TAG, "Unbinding backup agent with no active backup");
18495 return;
18496 }
18497
18498 if (!mBackupAppName.equals(appInfo.packageName)) {
18499 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
18500 return;
18501 }
18502
18503 // Not backing this app up any more; reset its OOM adjustment
18504 final ProcessRecord proc = mBackupTarget.app;
18505 updateOomAdjLocked(proc, true);
18506 proc.inFullBackup = false;
18507
18508 oldBackupUid = mBackupTarget != null ? mBackupTarget.appInfo.uid : -1;
18509
18510 // If the app crashed during backup, 'thread' will be null here
18511 if (proc.thread != null) {
18512 try {
18513 proc.thread.scheduleDestroyBackupAgent(appInfo,
18514 compatibilityInfoForPackageLocked(appInfo));
18515 } catch (Exception e) {
18516 Slog.e(TAG, "Exception when unbinding backup agent:");
18517 e.printStackTrace();
18518 }
18519 }
18520 } finally {
18521 mBackupTarget = null;
18522 mBackupAppName = null;
18523 }
18524 }
18525
18526 if (oldBackupUid != -1) {
18527 JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
18528 js.removeBackingUpUid(oldBackupUid);
18529 }
18530 }

broadcast相关

 18531
18532 // =========================================================
18533 // BROADCASTS
18534 // =========================================================
18535
18536 private boolean isInstantApp(ProcessRecord record, String callerPackage, int uid) {
18537 if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) {
18538 return false;
18539 }
18540 // Easy case -- we have the app's ProcessRecord.
18541 if (record != null) {
18542 return record.info.isInstantApp();
18543 }
18544 // Otherwise check with PackageManager.
18545 if (callerPackage == null) {
18546 Slog.e(TAG, "isInstantApp with an application's uid, no record, and no package name");
18547 throw new IllegalArgumentException("Calling application did not provide package name");
18548 }
18549 mAppOpsService.checkPackage(uid, callerPackage);
18550 try {
18551 IPackageManager pm = AppGlobals.getPackageManager();
18552 return pm.isInstantApp(callerPackage, UserHandle.getUserId(uid));
18553 } catch (RemoteException e) {
18554 Slog.e(TAG, "Error looking up if " + callerPackage + " is an instant app.", e);
18555 return true;
18556 }
18557 }
18558
18559 boolean isPendingBroadcastProcessLocked(int pid) {
18560 return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
18561 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
18562 }
18563
18564 void skipPendingBroadcastLocked(int pid) {
18565 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
18566 for (BroadcastQueue queue : mBroadcastQueues) {
18567 queue.skipPendingBroadcastLocked(pid);
18568 }
18569 }
18570
18571 // The app just attached; send any pending broadcasts that it should receive
18572 boolean sendPendingBroadcastsLocked(ProcessRecord app) {
18573 boolean didSomething = false;
18574 for (BroadcastQueue queue : mBroadcastQueues) {
18575 didSomething |= queue.sendPendingBroadcastsLocked(app);
18576 }
18577 return didSomething;
18578 }
18579
18580 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
18581 IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
18582 int flags) {
18583 enforceNotIsolatedCaller("registerReceiver");
18584 ArrayList<Intent> stickyIntents = null;
18585 ProcessRecord callerApp = null;
18586 final boolean visibleToInstantApps
18587 = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
18588 int callingUid;
18589 int callingPid;
18590 boolean instantApp;
18591 synchronized(this) {
18592 if (caller != null) {
18593 callerApp = getRecordForAppLocked(caller);
18594 if (callerApp == null) {
18595 throw new SecurityException(
18596 "Unable to find app for caller " + caller
18597 + " (pid=" + Binder.getCallingPid()
18598 + ") when registering receiver " + receiver);
18599 }
18600 if (callerApp.info.uid != SYSTEM_UID &&
18601 !callerApp.pkgList.containsKey(callerPackage) &&
18602 !"android".equals(callerPackage)) {
18603 throw new SecurityException("Given caller package " + callerPackage
18604 + " is not running in process " + callerApp);
18605 }
18606 callingUid = callerApp.info.uid;
18607 callingPid = callerApp.pid;
18608 } else {
18609 callerPackage = null;
18610 callingUid = Binder.getCallingUid();
18611 callingPid = Binder.getCallingPid();
18612 }
18613
18614 instantApp = isInstantApp(callerApp, callerPackage, callingUid);
18615 userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
18616 ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
18617
18618 Iterator<String> actions = filter.actionsIterator();
18619 if (actions == null) {
18620 ArrayList<String> noAction = new ArrayList<String>(1);
18621 noAction.add(null);
18622 actions = noAction.iterator();
18623 }
18624
18625 // Collect stickies of users
18626 int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
18627 while (actions.hasNext()) {
18628 String action = actions.next();
18629 for (int id : userIds) {
18630 ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
18631 if (stickies != null) {
18632 ArrayList<Intent> intents = stickies.get(action);
18633 if (intents != null) {
18634 if (stickyIntents == null) {
18635 stickyIntents = new ArrayList<Intent>();
18636 }
18637 stickyIntents.addAll(intents);
18638 }
18639 }
18640 }
18641 }
18642 }
18643
18644 ArrayList<Intent> allSticky = null;
18645 if (stickyIntents != null) {
18646 final ContentResolver resolver = mContext.getContentResolver();
18647 // Look for any matching sticky broadcasts...
18648 for (int i = 0, N = stickyIntents.size(); i < N; i++) {
18649 Intent intent = stickyIntents.get(i);
18650 // Don't provided intents that aren't available to instant apps.
18651 if (instantApp &&
18652 (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
18653 continue;
18654 }
18655 // If intent has scheme "content", it will need to acccess
18656 // provider that needs to lock mProviderMap in ActivityThread
18657 // and also it may need to wait application response, so we
18658 // cannot lock ActivityManagerService here.
18659 if (filter.match(resolver, intent, true, TAG) >= 0) {
18660 if (allSticky == null) {
18661 allSticky = new ArrayList<Intent>();
18662 }
18663 allSticky.add(intent);
18664 }
18665 }
18666 }
18667
18668 // The first sticky in the list is returned directly back to the client.
18669 Intent sticky = allSticky != null ? allSticky.get(0) : null;
18670 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
18671 if (receiver == null) {
18672 return sticky;
18673 }
18674
18675 synchronized (this) {
18676 if (callerApp != null && (callerApp.thread == null
18677 || callerApp.thread.asBinder() != caller.asBinder())) {
18678 // Original caller already died
18679 return null;
18680 }
18681 ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
18682 if (rl == null) {
18683 rl = new ReceiverList(this, callerApp, callingPid, callingUid,
18684 userId, receiver);
18685 if (rl.app != null) {
18686 rl.app.receivers.add(rl);
18687 } else {
18688 try {
18689 receiver.asBinder().linkToDeath(rl, 0);
18690 } catch (RemoteException e) {
18691 return sticky;
18692 }
18693 rl.linkedToDeath = true;
18694 }
18695 mRegisteredReceivers.put(receiver.asBinder(), rl);
18696 } else if (rl.uid != callingUid) {
18697 throw new IllegalArgumentException(
18698 "Receiver requested to register for uid " + callingUid
18699 + " was previously registered for uid " + rl.uid
18700 + " callerPackage is " + callerPackage);
18701 } else if (rl.pid != callingPid) {
18702 throw new IllegalArgumentException(
18703 "Receiver requested to register for pid " + callingPid
18704 + " was previously registered for pid " + rl.pid
18705 + " callerPackage is " + callerPackage);
18706 } else if (rl.userId != userId) {
18707 throw new IllegalArgumentException(
18708 "Receiver requested to register for user " + userId
18709 + " was previously registered for user " + rl.userId
18710 + " callerPackage is " + callerPackage);
18711 }
18712 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
18713 permission, callingUid, userId, instantApp, visibleToInstantApps);
18714 rl.add(bf);
18715 if (!bf.debugCheck()) {
18716 Slog.w(TAG, "==> For Dynamic broadcast");
18717 }
18718 mReceiverResolver.addFilter(bf);
18719
18720 // Enqueue broadcasts for all existing stickies that match
18721 // this filter.
18722 if (allSticky != null) {
18723 ArrayList receivers = new ArrayList();
18724 receivers.add(bf);
18725
18726 final int stickyCount = allSticky.size();
18727 for (int i = 0; i < stickyCount; i++) {
18728 Intent intent = allSticky.get(i);
18729 BroadcastQueue queue = broadcastQueueForIntent(intent);
18730 BroadcastRecord r = new BroadcastRecord(queue, intent, null,
18731 null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
18732 null, 0, null, null, false, true, true, -1);
18733 queue.enqueueParallelBroadcastLocked(r);
18734 queue.scheduleBroadcastsLocked();
18735 }
18736 }
18737
18738 return sticky;
18739 }
18740 }
18741
18742 public void unregisterReceiver(IIntentReceiver receiver) {
18743 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Unregister receiver: " + receiver);
18744
18745 final long origId = Binder.clearCallingIdentity();
18746 try {
18747 boolean doTrim = false;
18748
18749 synchronized(this) {
18750 ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
18751 if (rl != null) {
18752 final BroadcastRecord r = rl.curBroadcast;
18753 if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
18754 final boolean doNext = r.queue.finishReceiverLocked(
18755 r, r.resultCode, r.resultData, r.resultExtras,
18756 r.resultAbort, false);
18757 if (doNext) {
18758 doTrim = true;
18759 r.queue.processNextBroadcast(false);
18760 }
18761 }
18762
18763 if (rl.app != null) {
18764 rl.app.receivers.remove(rl);
18765 }
18766 removeReceiverLocked(rl);
18767 if (rl.linkedToDeath) {
18768 rl.linkedToDeath = false;
18769 rl.receiver.asBinder().unlinkToDeath(rl, 0);
18770 }
18771 }
18772 }
18773
18774 // If we actually concluded any broadcasts, we might now be able
18775 // to trim the recipients' apps from our working set
18776 if (doTrim) {
18777 trimApplications();
18778 return;
18779 }
18780
18781 } finally {
18782 Binder.restoreCallingIdentity(origId);
18783 }
18784 }
18785
18786 void removeReceiverLocked(ReceiverList rl) {
18787 mRegisteredReceivers.remove(rl.receiver.asBinder());
18788 for (int i = rl.size() - 1; i >= 0; i--) {
18789 mReceiverResolver.removeFilter(rl.get(i));
18790 }
18791 }
18792
18793 private final void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
18794 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
18795 ProcessRecord r = mLruProcesses.get(i);
18796 if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
18797 try {
18798 r.thread.dispatchPackageBroadcast(cmd, packages);
18799 } catch (RemoteException ex) {
18800 }
18801 }
18802 }
18803 }
18804
18805 private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
18806 int callingUid, int[] users) {
18807 // TODO: come back and remove this assumption to triage all broadcasts
18808 int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
18809
18810 List<ResolveInfo> receivers = null;
18811 try {
18812 HashSet<ComponentName> singleUserReceivers = null;
18813 boolean scannedFirstReceivers = false;
18814 for (int user : users) {
18815 // Skip users that have Shell restrictions, with exception of always permitted
18816 // Shell broadcasts
18817 if (callingUid == SHELL_UID
18818 && mUserController.hasUserRestriction(
18819 UserManager.DISALLOW_DEBUGGING_FEATURES, user)
18820 && !isPermittedShellBroadcast(intent)) {
18821 continue;
18822 }
18823 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
18824 .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
18825 if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
18826 // If this is not the system user, we need to check for
18827 // any receivers that should be filtered out.
18828 for (int i=0; i<newReceivers.size(); i++) {
18829 ResolveInfo ri = newReceivers.get(i);
18830 if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
18831 newReceivers.remove(i);
18832 i--;
18833 }
18834 }
18835 }
18836 if (newReceivers != null && newReceivers.size() == 0) {
18837 newReceivers = null;
18838 }
18839 if (receivers == null) {
18840 receivers = newReceivers;
18841 } else if (newReceivers != null) {
18842 // We need to concatenate the additional receivers
18843 // found with what we have do far. This would be easy,
18844 // but we also need to de-dup any receivers that are
18845 // singleUser.
18846 if (!scannedFirstReceivers) {
18847 // Collect any single user receivers we had already retrieved.
18848 scannedFirstReceivers = true;
18849 for (int i=0; i<receivers.size(); i++) {
18850 ResolveInfo ri = receivers.get(i);
18851 if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
18852 ComponentName cn = new ComponentName(
18853 ri.activityInfo.packageName, ri.activityInfo.name);
18854 if (singleUserReceivers == null) {
18855 singleUserReceivers = new HashSet<ComponentName>();
18856 }
18857 singleUserReceivers.add(cn);
18858 }
18859 }
18860 }
18861 // Add the new results to the existing results, tracking
18862 // and de-dupping single user receivers.
18863 for (int i=0; i<newReceivers.size(); i++) {
18864 ResolveInfo ri = newReceivers.get(i);
18865 if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
18866 ComponentName cn = new ComponentName(
18867 ri.activityInfo.packageName, ri.activityInfo.name);
18868 if (singleUserReceivers == null) {
18869 singleUserReceivers = new HashSet<ComponentName>();
18870 }
18871 if (!singleUserReceivers.contains(cn)) {
18872 singleUserReceivers.add(cn);
18873 receivers.add(ri);
18874 }
18875 } else {
18876 receivers.add(ri);
18877 }
18878 }
18879 }
18880 }
18881 } catch (RemoteException ex) {
18882 // pm is in same process, this will never happen.
18883 }
18884 return receivers;
18885 }
18886
18887 private boolean isPermittedShellBroadcast(Intent intent) {
18888 // remote bugreport should always be allowed to be taken
18889 return INTENT_REMOTE_BUGREPORT_FINISHED.equals(intent.getAction());
18890 }
18891
18892 private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
18893 String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
18894 if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
18895 // Don't yell about broadcasts sent via shell
18896 return;
18897 }
18898
18899 final String action = intent.getAction();
18900 if (isProtectedBroadcast
18901 || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
18902 || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
18903 || Intent.ACTION_MEDIA_BUTTON.equals(action)
18904 || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
18905 || Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)
18906 || Intent.ACTION_MASTER_CLEAR.equals(action)
18907 || Intent.ACTION_FACTORY_RESET.equals(action)
18908 || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
18909 || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
18910 || LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
18911 || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
18912 || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)
18913 || AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION.equals(action)
18914 || AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION.equals(action)) {
18915 // Broadcast is either protected, or it's a public action that
18916 // we've relaxed, so it's fine for system internals to send.
18917 return;
18918 }
18919
18920 // This broadcast may be a problem... but there are often system components that
18921 // want to send an internal broadcast to themselves, which is annoying to have to
18922 // explicitly list each action as a protected broadcast, so we will check for that
18923 // one safe case and allow it: an explicit broadcast, only being received by something
18924 // that has protected itself.
18925 if (receivers != null && receivers.size() > 0
18926 && (intent.getPackage() != null || intent.getComponent() != null)) {
18927 boolean allProtected = true;
18928 for (int i = receivers.size()-1; i >= 0; i--) {
18929 Object target = receivers.get(i);
18930 if (target instanceof ResolveInfo) {
18931 ResolveInfo ri = (ResolveInfo)target;
18932 if (ri.activityInfo.exported && ri.activityInfo.permission == null) {
18933 allProtected = false;
18934 break;
18935 }
18936 } else {
18937 BroadcastFilter bf = (BroadcastFilter)target;
18938 if (bf.requiredPermission == null) {
18939 allProtected = false;
18940 break;
18941 }
18942 }
18943 }
18944 if (allProtected) {
18945 // All safe!
18946 return;
18947 }
18948 }
18949
18950 // The vast majority of broadcasts sent from system internals
18951 // should be protected to avoid security holes, so yell loudly
18952 // to ensure we examine these cases.
18953 if (callerApp != null) {
18954 Log.wtf(TAG, "Sending non-protected broadcast " + action
18955 + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
18956 new Throwable());
18957 } else {
18958 Log.wtf(TAG, "Sending non-protected broadcast " + action
18959 + " from system uid " + UserHandle.formatUid(callingUid)
18960 + " pkg " + callerPackage,
18961 new Throwable());
18962 }
18963 }
18964
18965 final int broadcastIntentLocked(ProcessRecord callerApp,
18966 String callerPackage, Intent intent, String resolvedType,
18967 IIntentReceiver resultTo, int resultCode, String resultData,
18968 Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
18969 boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
18970 intent = new Intent(intent);
18971
18972 final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
18973 // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
18974 if (callerInstantApp) {
18975 intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
18976 }
18977
18978 // By default broadcasts do not go to stopped apps.
18979 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
18980
18981 // If we have not finished booting, don't allow this to launch new processes.
18982 if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
18983 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
18984 }
18985
18986 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
18987 (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
18988 + " ordered=" + ordered + " userid=" + userId);
18989 if ((resultTo != null) && !ordered) {
18990 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
18991 }
18992
18993 userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
18994 ALLOW_NON_FULL, "broadcast", callerPackage);
18995
18996 // Make sure that the user who is receiving this broadcast is running.
18997 // If not, we will just skip it. Make an exception for shutdown broadcasts
18998 // and upgrade steps.
18999
19000 if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
19001 if ((callingUid != SYSTEM_UID
19002 || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
19003 && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
19004 Slog.w(TAG, "Skipping broadcast of " + intent
19005 + ": user " + userId + " is stopped");
19006 return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
19007 }
19008 }
19009
19010 BroadcastOptions brOptions = null;
19011 if (bOptions != null) {
19012 brOptions = new BroadcastOptions(bOptions);
19013 if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
19014 // See if the caller is allowed to do this. Note we are checking against
19015 // the actual real caller (not whoever provided the operation as say a
19016 // PendingIntent), because that who is actually supplied the arguments.
19017 if (checkComponentPermission(
19018 android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
19019 Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
19020 != PackageManager.PERMISSION_GRANTED) {
19021 String msg = "Permission Denial: " + intent.getAction()
19022 + " broadcast from " + callerPackage + " (pid=" + callingPid
19023 + ", uid=" + callingUid + ")"
19024 + " requires "
19025 + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
19026 Slog.w(TAG, msg);
19027 throw new SecurityException(msg);
19028 }
19029 }
19030 }
19031
19032 // Verify that protected broadcasts are only being sent by system code,
19033 // and that system code is only sending protected broadcasts.
19034 final String action = intent.getAction();
19035 final boolean isProtectedBroadcast;
19036 try {
19037 isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
19038 } catch (RemoteException e) {
19039 Slog.w(TAG, "Remote exception", e);
19040 return ActivityManager.BROADCAST_SUCCESS;
19041 }
19042
19043 final boolean isCallerSystem;
19044 switch (UserHandle.getAppId(callingUid)) {
19045 case ROOT_UID:
19046 case SYSTEM_UID:
19047 case PHONE_UID:
19048 case BLUETOOTH_UID:
19049 case NFC_UID:
19050 isCallerSystem = true;
19051 break;
19052 default:
19053 isCallerSystem = (callerApp != null) && callerApp.persistent;
19054 break;
19055 }
19056
19057 // First line security check before anything else: stop non-system apps from
19058 // sending protected broadcasts.
19059 if (!isCallerSystem) {
19060 if (isProtectedBroadcast) {
19061 String msg = "Permission Denial: not allowed to send broadcast "
19062 + action + " from pid="
19063 + callingPid + ", uid=" + callingUid;
19064 Slog.w(TAG, msg);
19065 throw new SecurityException(msg);
19066
19067 } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
19068 || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
19069 // Special case for compatibility: we don't want apps to send this,
19070 // but historically it has not been protected and apps may be using it
19071 // to poke their own app widget. So, instead of making it protected,
19072 // just limit it to the caller.
19073 if (callerPackage == null) {
19074 String msg = "Permission Denial: not allowed to send broadcast "
19075 + action + " from unknown caller.";
19076 Slog.w(TAG, msg);
19077 throw new SecurityException(msg);
19078 } else if (intent.getComponent() != null) {
19079 // They are good enough to send to an explicit component... verify
19080 // it is being sent to the calling app.
19081 if (!intent.getComponent().getPackageName().equals(
19082 callerPackage)) {
19083 String msg = "Permission Denial: not allowed to send broadcast "
19084 + action + " to "
19085 + intent.getComponent().getPackageName() + " from "
19086 + callerPackage;
19087 Slog.w(TAG, msg);
19088 throw new SecurityException(msg);
19089 }
19090 } else {
19091 // Limit broadcast to their own package.
19092 intent.setPackage(callerPackage);
19093 }
19094 }
19095 }
19096
19097 if (action != null) {
19098 if (getBackgroundLaunchBroadcasts().contains(action)) {
19099 if (DEBUG_BACKGROUND_CHECK) {
19100 Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
19101 }
19102 intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
19103 }
19104
19105 switch (action) {
19106 case Intent.ACTION_UID_REMOVED:
19107 case Intent.ACTION_PACKAGE_REMOVED:
19108 case Intent.ACTION_PACKAGE_CHANGED:
19109 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
19110 case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
19111 case Intent.ACTION_PACKAGES_SUSPENDED:
19112 case Intent.ACTION_PACKAGES_UNSUSPENDED:
19113 // Handle special intents: if this broadcast is from the package
19114 // manager about a package being removed, we need to remove all of
19115 // its activities from the history stack.
19116 if (checkComponentPermission(
19117 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
19118 callingPid, callingUid, -1, true)
19119 != PackageManager.PERMISSION_GRANTED) {
19120 String msg = "Permission Denial: " + intent.getAction()
19121 + " broadcast from " + callerPackage + " (pid=" + callingPid
19122 + ", uid=" + callingUid + ")"
19123 + " requires "
19124 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
19125 Slog.w(TAG, msg);
19126 throw new SecurityException(msg);
19127 }
19128 switch (action) {
19129 case Intent.ACTION_UID_REMOVED:
19130 final int uid = getUidFromIntent(intent);
19131 if (uid >= 0) {
19132 mBatteryStatsService.removeUid(uid);
19133 mAppOpsService.uidRemoved(uid);
19134 }
19135 break;
19136 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
19137 // If resources are unavailable just force stop all those packages
19138 // and flush the attribute cache as well.
19139 String list[] =
19140 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
19141 if (list != null && list.length > 0) {
19142 for (int i = 0; i < list.length; i++) {
19143 forceStopPackageLocked(list[i], -1, false, true, true,
19144 false, false, userId, "storage unmount");
19145 }
19146 mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
19147 sendPackageBroadcastLocked(
19148 ApplicationThreadConstants.EXTERNAL_STORAGE_UNAVAILABLE,
19149 list, userId);
19150 }
19151 break;
19152 case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
19153 mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
19154 break;
19155 case Intent.ACTION_PACKAGE_REMOVED:
19156 case Intent.ACTION_PACKAGE_CHANGED:
19157 Uri data = intent.getData();
19158 String ssp;
19159 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
19160 boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
19161 final boolean replacing =
19162 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
19163 final boolean killProcess =
19164 !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
19165 final boolean fullUninstall = removed && !replacing;
19166 if (removed) {
19167 if (killProcess) {
19168 forceStopPackageLocked(ssp, UserHandle.getAppId(
19169 intent.getIntExtra(Intent.EXTRA_UID, -1)),
19170 false, true, true, false, fullUninstall, userId,
19171 removed ? "pkg removed" : "pkg changed");
19172 }
19173 final int cmd = killProcess
19174 ? ApplicationThreadConstants.PACKAGE_REMOVED
19175 : ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL;
19176 sendPackageBroadcastLocked(cmd,
19177 new String[] {ssp}, userId);
19178 if (fullUninstall) {
19179 mAppOpsService.packageRemoved(
19180 intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
19181
19182 // Remove all permissions granted from/to this package
19183 removeUriPermissionsForPackageLocked(ssp, userId, true);
19184
19185 removeTasksByPackageNameLocked(ssp, userId);
19186
19187 mServices.forceStopPackageLocked(ssp, userId);
19188
19189 // Hide the "unsupported display" dialog if necessary.
19190 if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
19191 mUnsupportedDisplaySizeDialog.getPackageName())) {
19192 mUnsupportedDisplaySizeDialog.dismiss();
19193 mUnsupportedDisplaySizeDialog = null;
19194 }
19195 mCompatModePackages.handlePackageUninstalledLocked(ssp);
19196 mBatteryStatsService.notePackageUninstalled(ssp);
19197 }
19198 } else {
19199 if (killProcess) {
19200 killPackageProcessesLocked(ssp, UserHandle.getAppId(
19201 intent.getIntExtra(Intent.EXTRA_UID, -1)),
19202 userId, ProcessList.INVALID_ADJ,
19203 false, true, true, false, "change " + ssp);
19204 }
19205 cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
19206 intent.getStringArrayExtra(
19207 Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
19208 }
19209 }
19210 break;
19211 case Intent.ACTION_PACKAGES_SUSPENDED:
19212 case Intent.ACTION_PACKAGES_UNSUSPENDED:
19213 final boolean suspended = Intent.ACTION_PACKAGES_SUSPENDED.equals(
19214 intent.getAction());
19215 final String[] packageNames = intent.getStringArrayExtra(
19216 Intent.EXTRA_CHANGED_PACKAGE_LIST);
19217 final int userHandle = intent.getIntExtra(
19218 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
19219
19220 synchronized(ActivityManagerService.this) {
19221 mRecentTasks.onPackagesSuspendedChanged(
19222 packageNames, suspended, userHandle);
19223 }
19224 break;
19225 }
19226 break;
19227 case Intent.ACTION_PACKAGE_REPLACED:
19228 {
19229 final Uri data = intent.getData();
19230 final String ssp;
19231 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
19232 ApplicationInfo aInfo = null;
19233 try {
19234 aInfo = AppGlobals.getPackageManager()
19235 .getApplicationInfo(ssp, 0 /*flags*/, userId);
19236 } catch (RemoteException ignore) {}
19237 if (aInfo == null) {
19238 Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
19239 + " ssp=" + ssp + " data=" + data);
19240 return ActivityManager.BROADCAST_SUCCESS;
19241 }
19242 mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
19243 sendPackageBroadcastLocked(ApplicationThreadConstants.PACKAGE_REPLACED,
19244 new String[] {ssp}, userId);
19245 }
19246 break;
19247 }
19248 case Intent.ACTION_PACKAGE_ADDED:
19249 {
19250 // Special case for adding a package: by default turn on compatibility mode.
19251 Uri data = intent.getData();
19252 String ssp;
19253 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
19254 final boolean replacing =
19255 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
19256 mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
19257
19258 try {
19259 ApplicationInfo ai = AppGlobals.getPackageManager().
19260 getApplicationInfo(ssp, 0, 0);
19261 mBatteryStatsService.notePackageInstalled(ssp,
19262 ai != null ? ai.versionCode : 0);
19263 } catch (RemoteException e) {
19264 }
19265 }
19266 break;
19267 }
19268 case Intent.ACTION_PACKAGE_DATA_CLEARED:
19269 {
19270 Uri data = intent.getData();
19271 String ssp;
19272 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
19273 // Hide the "unsupported display" dialog if necessary.
19274 if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
19275 mUnsupportedDisplaySizeDialog.getPackageName())) {
19276 mUnsupportedDisplaySizeDialog.dismiss();
19277 mUnsupportedDisplaySizeDialog = null;
19278 }
19279 mCompatModePackages.handlePackageDataClearedLocked(ssp);
19280 }
19281 break;
19282 }
19283 case Intent.ACTION_TIMEZONE_CHANGED:
19284 // If this is the time zone changed action, queue up a message that will reset
19285 // the timezone of all currently running processes. This message will get
19286 // queued up before the broadcast happens.
19287 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
19288 break;
19289 case Intent.ACTION_TIME_CHANGED:
19290 // EXTRA_TIME_PREF_24_HOUR_FORMAT is optional so we must distinguish between
19291 // the tri-state value it may contain and "unknown".
19292 // For convenience we re-use the Intent extra values.
19293 final int NO_EXTRA_VALUE_FOUND = -1;
19294 final int timeFormatPreferenceMsgValue = intent.getIntExtra(
19295 Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
19296 NO_EXTRA_VALUE_FOUND /* defaultValue */);
19297 // Only send a message if the time preference is available.
19298 if (timeFormatPreferenceMsgValue != NO_EXTRA_VALUE_FOUND) {
19299 Message updateTimePreferenceMsg =
19300 mHandler.obtainMessage(UPDATE_TIME_PREFERENCE_MSG,
19301 timeFormatPreferenceMsgValue, 0);
19302 mHandler.sendMessage(updateTimePreferenceMsg);
19303 }
19304 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
19305 synchronized (stats) {
19306 stats.noteCurrentTimeChangedLocked();
19307 }
19308 break;
19309 case Intent.ACTION_CLEAR_DNS_CACHE:
19310 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
19311 break;
19312 case Proxy.PROXY_CHANGE_ACTION:
19313 ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
19314 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
19315 break;
19316 case android.hardware.Camera.ACTION_NEW_PICTURE:
19317 case android.hardware.Camera.ACTION_NEW_VIDEO:
19318 // In N we just turned these off; in O we are turing them back on partly,
19319 // only for registered receivers. This will still address the main problem
19320 // (a spam of apps waking up when a picture is taken putting significant
19321 // memory pressure on the system at a bad point), while still allowing apps
19322 // that are already actively running to know about this happening.
19323 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
19324 break;
19325 case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED:
19326 mHandler.sendEmptyMessage(HANDLE_TRUST_STORAGE_UPDATE_MSG);
19327 break;
19328 case "com.android.launcher.action.INSTALL_SHORTCUT":
19329 // As of O, we no longer support this broadcasts, even for pre-O apps.
19330 // Apps should now be using ShortcutManager.pinRequestShortcut().
19331 Log.w(TAG, "Broadcast " + action
19332 + " no longer supported. It will not be delivered.");
19333 return ActivityManager.BROADCAST_SUCCESS;
19334 }
19335
19336 if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
19337 Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
19338 Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
19339 final int uid = getUidFromIntent(intent);
19340 if (uid != -1) {
19341 final UidRecord uidRec = mActiveUids.get(uid);
19342 if (uidRec != null) {
19343 uidRec.updateHasInternetPermission();
19344 }
19345 }
19346 }
19347 }
19348
19349 // Add to the sticky list if requested.
19350 if (sticky) {
19351 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
19352 callingPid, callingUid)
19353 != PackageManager.PERMISSION_GRANTED) {
19354 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
19355 + callingPid + ", uid=" + callingUid
19356 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
19357 Slog.w(TAG, msg);
19358 throw new SecurityException(msg);
19359 }
19360 if (requiredPermissions != null && requiredPermissions.length > 0) {
19361 Slog.w(TAG, "Can't broadcast sticky intent " + intent
19362 + " and enforce permissions " + Arrays.toString(requiredPermissions));
19363 return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
19364 }
19365 if (intent.getComponent() != null) {
19366 throw new SecurityException(
19367 "Sticky broadcasts can't target a specific component");
19368 }
19369 // We use userId directly here, since the "all" target is maintained
19370 // as a separate set of sticky broadcasts.
19371 if (userId != UserHandle.USER_ALL) {
19372 // But first, if this is not a broadcast to all users, then
19373 // make sure it doesn't conflict with an existing broadcast to
19374 // all users.
19375 ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
19376 UserHandle.USER_ALL);
19377 if (stickies != null) {
19378 ArrayList<Intent> list = stickies.get(intent.getAction());
19379 if (list != null) {
19380 int N = list.size();
19381 int i;
19382 for (i=0; i<N; i++) {
19383 if (intent.filterEquals(list.get(i))) {
19384 throw new IllegalArgumentException(
19385 "Sticky broadcast " + intent + " for user "
19386 + userId + " conflicts with existing global broadcast");
19387 }
19388 }
19389 }
19390 }
19391 }
19392 ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
19393 if (stickies == null) {
19394 stickies = new ArrayMap<>();
19395 mStickyBroadcasts.put(userId, stickies);
19396 }
19397 ArrayList<Intent> list = stickies.get(intent.getAction());
19398 if (list == null) {
19399 list = new ArrayList<>();
19400 stickies.put(intent.getAction(), list);
19401 }
19402 final int stickiesCount = list.size();
19403 int i;
19404 for (i = 0; i < stickiesCount; i++) {
19405 if (intent.filterEquals(list.get(i))) {
19406 // This sticky already exists, replace it.
19407 list.set(i, new Intent(intent));
19408 break;
19409 }
19410 }
19411 if (i >= stickiesCount) {
19412 list.add(new Intent(intent));
19413 }
19414 }
19415
19416 int[] users;
19417 if (userId == UserHandle.USER_ALL) {
19418 // Caller wants broadcast to go to all started users.
19419 users = mUserController.getStartedUserArrayLocked();
19420 } else {
19421 // Caller wants broadcast to go to one specific user.
19422 users = new int[] {userId};
19423 }
19424
19425 // Figure out who all will receive this broadcast.
19426 List receivers = null;
19427 List<BroadcastFilter> registeredReceivers = null;
19428 // Need to resolve the intent to interested receivers...
19429 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
19430 == 0) {
19431 receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
19432 }
19433 if (intent.getComponent() == null) {
19434 if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
19435 // Query one target user at a time, excluding shell-restricted users
19436 for (int i = 0; i < users.length; i++) {
19437 if (mUserController.hasUserRestriction(
19438 UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
19439 continue;
19440 }
19441 List<BroadcastFilter> registeredReceiversForUser =
19442 mReceiverResolver.queryIntent(intent,
19443 resolvedType, false /*defaultOnly*/, users[i]);
19444 if (registeredReceivers == null) {
19445 registeredReceivers = registeredReceiversForUser;
19446 } else if (registeredReceiversForUser != null) {
19447 registeredReceivers.addAll(registeredReceiversForUser);
19448 }
19449 }
19450 } else {
19451 registeredReceivers = mReceiverResolver.queryIntent(intent,
19452 resolvedType, false /*defaultOnly*/, userId);
19453 }
19454 }
19455
19456 final boolean replacePending =
19457 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
19458
19459 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
19460 + " replacePending=" + replacePending);
19461
19462 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
19463 if (!ordered && NR > 0) {
19464 // If we are not serializing this broadcast, then send the
19465 // registered receivers separately so they don't wait for the
19466 // components to be launched.
19467 if (isCallerSystem) {
19468 checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
19469 isProtectedBroadcast, registeredReceivers);
19470 }
19471 final BroadcastQueue queue = broadcastQueueForIntent(intent);
19472 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
19473 callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
19474 requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
19475 resultCode, resultData, resultExtras, ordered, sticky, false, userId);
19476 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
19477 final boolean replaced = replacePending
19478 && (queue.replaceParallelBroadcastLocked(r) != null);
19479 // Note: We assume resultTo is null for non-ordered broadcasts.
19480 if (!replaced) {
19481 queue.enqueueParallelBroadcastLocked(r);
19482 queue.scheduleBroadcastsLocked();
19483 }
19484 registeredReceivers = null;
19485 NR = 0;
19486 }
19487
19488 // Merge into one list.
19489 int ir = 0;
19490 if (receivers != null) {
19491 // A special case for PACKAGE_ADDED: do not allow the package
19492 // being added to see this broadcast. This prevents them from
19493 // using this as a back door to get run as soon as they are
19494 // installed. Maybe in the future we want to have a special install
19495 // broadcast or such for apps, but we'd like to deliberately make
19496 // this decision.
19497 String skipPackages[] = null;
19498 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
19499 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
19500 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
19501 Uri data = intent.getData();
19502 if (data != null) {
19503 String pkgName = data.getSchemeSpecificPart();
19504 if (pkgName != null) {
19505 skipPackages = new String[] { pkgName };
19506 }
19507 }
19508 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
19509 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
19510 }
19511 if (skipPackages != null && (skipPackages.length > 0)) {
19512 for (String skipPackage : skipPackages) {
19513 if (skipPackage != null) {
19514 int NT = receivers.size();
19515 for (int it=0; it<NT; it++) {
19516 ResolveInfo curt = (ResolveInfo)receivers.get(it);
19517 if (curt.activityInfo.packageName.equals(skipPackage)) {
19518 receivers.remove(it);
19519 it--;
19520 NT--;
19521 }
19522 }
19523 }
19524 }
19525 }
19526
19527 int NT = receivers != null ? receivers.size() : 0;
19528 int it = 0;
19529 ResolveInfo curt = null;
19530 BroadcastFilter curr = null;
19531 while (it < NT && ir < NR) {
19532 if (curt == null) {
19533 curt = (ResolveInfo)receivers.get(it);
19534 }
19535 if (curr == null) {
19536 curr = registeredReceivers.get(ir);
19537 }
19538 if (curr.getPriority() >= curt.priority) {
19539 // Insert this broadcast record into the final list.
19540 receivers.add(it, curr);
19541 ir++;
19542 curr = null;
19543 it++;
19544 NT++;
19545 } else {
19546 // Skip to the next ResolveInfo in the final list.
19547 it++;
19548 curt = null;
19549 }
19550 }
19551 }
19552 while (ir < NR) {
19553 if (receivers == null) {
19554 receivers = new ArrayList();
19555 }
19556 receivers.add(registeredReceivers.get(ir));
19557 ir++;
19558 }
19559
19560 if (isCallerSystem) {
19561 checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
19562 isProtectedBroadcast, receivers);
19563 }
19564
19565 if ((receivers != null && receivers.size() > 0)
19566 || resultTo != null) {
19567 BroadcastQueue queue = broadcastQueueForIntent(intent);
19568 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
19569 callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
19570 requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
19571 resultData, resultExtras, ordered, sticky, false, userId);
19572
19573 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
19574 + ": prev had " + queue.mOrderedBroadcasts.size());
19575 if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
19576 "Enqueueing broadcast " + r.intent.getAction());
19577
19578 final BroadcastRecord oldRecord =
19579 replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
19580 if (oldRecord != null) {
19581 // Replaced, fire the result-to receiver.
19582 if (oldRecord.resultTo != null) {
19583 final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
19584 try {
19585 oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
19586 oldRecord.intent,
19587 Activity.RESULT_CANCELED, null, null,
19588 false, false, oldRecord.userId);
19589 } catch (RemoteException e) {
19590 Slog.w(TAG, "Failure ["
19591 + queue.mQueueName + "] sending broadcast result of "
19592 + intent, e);
19593
19594 }
19595 }
19596 } else {
19597 queue.enqueueOrderedBroadcastLocked(r);
19598 queue.scheduleBroadcastsLocked();
19599 }
19600 } else {
19601 // There was nobody interested in the broadcast, but we still want to record
19602 // that it happened.
19603 if (intent.getComponent() == null && intent.getPackage() == null
19604 && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
19605 // This was an implicit broadcast... let's record it for posterity.
19606 addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
19607 }
19608 }
19609
19610 return ActivityManager.BROADCAST_SUCCESS;
19611 }
19612
19613 /**
19614 * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1
19615 */
19616 private int getUidFromIntent(Intent intent) {
19617 if (intent == null) {
19618 return -1;
19619 }
19620 final Bundle intentExtras = intent.getExtras();
19621 return intent.hasExtra(Intent.EXTRA_UID)
19622 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
19623 }
19624
19625 final void rotateBroadcastStatsIfNeededLocked() {
19626 final long now = SystemClock.elapsedRealtime();
19627 if (mCurBroadcastStats == null ||
19628 (mCurBroadcastStats.mStartRealtime +(24*60*60*1000) < now)) {
19629 mLastBroadcastStats = mCurBroadcastStats;
19630 if (mLastBroadcastStats != null) {
19631 mLastBroadcastStats.mEndRealtime = SystemClock.elapsedRealtime();
19632 mLastBroadcastStats.mEndUptime = SystemClock.uptimeMillis();
19633 }
19634 mCurBroadcastStats = new BroadcastStats();
19635 }
19636 }
19637
19638 final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
19639 int skipCount, long dispatchTime) {
19640 rotateBroadcastStatsIfNeededLocked();
19641 mCurBroadcastStats.addBroadcast(action, srcPackage, receiveCount, skipCount, dispatchTime);
19642 }
19643
19644 final void addBackgroundCheckViolationLocked(String action, String targetPackage) {
19645 rotateBroadcastStatsIfNeededLocked();
19646 mCurBroadcastStats.addBackgroundCheckViolation(action, targetPackage);
19647 }
19648
19649 final Intent verifyBroadcastLocked(Intent intent) {
19650 // Refuse possible leaked file descriptors
19651 if (intent != null && intent.hasFileDescriptors() == true) {
19652 throw new IllegalArgumentException("File descriptors passed in Intent");
19653 }
19654
19655 int flags = intent.getFlags();
19656
19657 if (!mProcessesReady) {
19658 // if the caller really truly claims to know what they're doing, go
19659 // ahead and allow the broadcast without launching any receivers
19660 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
19661 // This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.
19662 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
19663 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
19664 + " before boot completion");
19665 throw new IllegalStateException("Cannot broadcast before boot completed");
19666 }
19667 }
19668
19669 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
19670 throw new IllegalArgumentException(
19671 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
19672 }
19673
19674 if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
19675 switch (Binder.getCallingUid()) {
19676 case ROOT_UID:
19677 case SHELL_UID:
19678 break;
19679 default:
19680 Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "
19681 + Binder.getCallingUid());
19682 intent.removeFlags(Intent.FLAG_RECEIVER_FROM_SHELL);
19683 break;
19684 }
19685 }
19686
19687 return intent;
19688 }
19689
19690 public final int broadcastIntent(IApplicationThread caller,
19691 Intent intent, String resolvedType, IIntentReceiver resultTo,
19692 int resultCode, String resultData, Bundle resultExtras,
19693 String[] requiredPermissions, int appOp, Bundle bOptions,
19694 boolean serialized, boolean sticky, int userId) {
19695 enforceNotIsolatedCaller("broadcastIntent");
19696 synchronized(this) {
19697 intent = verifyBroadcastLocked(intent);
19698
19699 final ProcessRecord callerApp = getRecordForAppLocked(caller);
19700 final int callingPid = Binder.getCallingPid();
19701 final int callingUid = Binder.getCallingUid();
19702 final long origId = Binder.clearCallingIdentity();
19703 int res = broadcastIntentLocked(callerApp,
19704 callerApp != null ? callerApp.info.packageName : null,
19705 intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
19706 requiredPermissions, appOp, bOptions, serialized, sticky,
19707 callingPid, callingUid, userId);
19708 Binder.restoreCallingIdentity(origId);
19709 return res;
19710 }
19711 }
19712
19713
19714 int broadcastIntentInPackage(String packageName, int uid,
19715 Intent intent, String resolvedType, IIntentReceiver resultTo,
19716 int resultCode, String resultData, Bundle resultExtras,
19717 String requiredPermission, Bundle bOptions, boolean serialized, boolean sticky,
19718 int userId) {
19719 synchronized(this) {
19720 intent = verifyBroadcastLocked(intent);
19721
19722 final long origId = Binder.clearCallingIdentity();
19723 String[] requiredPermissions = requiredPermission == null ? null
19724 : new String[] {requiredPermission};
19725 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
19726 resultTo, resultCode, resultData, resultExtras,
19727 requiredPermissions, AppOpsManager.OP_NONE, bOptions, serialized,
19728 sticky, -1, uid, userId);
19729 Binder.restoreCallingIdentity(origId);
19730 return res;
19731 }
19732 }
19733
19734 public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) {
19735 // Refuse possible leaked file descriptors
19736 if (intent != null && intent.hasFileDescriptors() == true) {
19737 throw new IllegalArgumentException("File descriptors passed in Intent");
19738 }
19739
19740 userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
19741 userId, true, ALLOW_NON_FULL, "removeStickyBroadcast", null);
19742
19743 synchronized(this) {
19744 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
19745 != PackageManager.PERMISSION_GRANTED) {
19746 String msg = "Permission Denial: unbroadcastIntent() from pid="
19747 + Binder.getCallingPid()
19748 + ", uid=" + Binder.getCallingUid()
19749 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
19750 Slog.w(TAG, msg);
19751 throw new SecurityException(msg);
19752 }
19753 ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
19754 if (stickies != null) {
19755 ArrayList<Intent> list = stickies.get(intent.getAction());
19756 if (list != null) {
19757 int N = list.size();
19758 int i;
19759 for (i=0; i<N; i++) {
19760 if (intent.filterEquals(list.get(i))) {
19761 list.remove(i);
19762 break;
19763 }
19764 }
19765 if (list.size() <= 0) {
19766 stickies.remove(intent.getAction());
19767 }
19768 }
19769 if (stickies.size() <= 0) {
19770 mStickyBroadcasts.remove(userId);
19771 }
19772 }
19773 }
19774 }
19775
19776 void backgroundServicesFinishedLocked(int userId) {
19777 for (BroadcastQueue queue : mBroadcastQueues) {
19778 queue.backgroundServicesFinishedLocked(userId);
19779 }
19780 }
19781
19782 public void finishReceiver(IBinder who, int resultCode, String resultData,
19783 Bundle resultExtras, boolean resultAbort, int flags) {
19784 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + who);
19785
19786 // Refuse possible leaked file descriptors
19787 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
19788 throw new IllegalArgumentException("File descriptors passed in Bundle");
19789 }
19790
19791 final long origId = Binder.clearCallingIdentity();
19792 try {
19793 boolean doNext = false;
19794 BroadcastRecord r;
19795
19796 synchronized(this) {
19797 BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
19798 ? mFgBroadcastQueue : mBgBroadcastQueue;
19799 r = queue.getMatchingOrderedReceiver(who);
19800 if (r != null) {
19801 doNext = r.queue.finishReceiverLocked(r, resultCode,
19802 resultData, resultExtras, resultAbort, true);
19803 }
19804 }
19805
19806 if (doNext) {
19807 r.queue.processNextBroadcast(false);
19808 }
19809 trimApplications();
19810 } finally {
19811 Binder.restoreCallingIdentity(origId);
19812 }
19813 }

instrumentation相关

 19815    // =========================================================
19816 // INSTRUMENTATION
19817 // =========================================================
19818
19819 public boolean startInstrumentation(ComponentName className,
19820 String profileFile, int flags, Bundle arguments,
19821 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
19822 int userId, String abiOverride) {
19823 enforceNotIsolatedCaller("startInstrumentation");
19824 userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
19825 userId, false, ALLOW_FULL_ONLY, "startInstrumentation", null);
19826 // Refuse possible leaked file descriptors
19827 if (arguments != null && arguments.hasFileDescriptors()) {
19828 throw new IllegalArgumentException("File descriptors passed in Bundle");
19829 }
19830
19831 synchronized(this) {
19832 InstrumentationInfo ii = null;
19833 ApplicationInfo ai = null;
19834 try {
19835 ii = mContext.getPackageManager().getInstrumentationInfo(
19836 className, STOCK_PM_FLAGS);
19837 ai = AppGlobals.getPackageManager().getApplicationInfo(
19838 ii.targetPackage, STOCK_PM_FLAGS, userId);
19839 } catch (PackageManager.NameNotFoundException e) {
19840 } catch (RemoteException e) {
19841 }
19842 if (ii == null) {
19843 reportStartInstrumentationFailureLocked(watcher, className,
19844 "Unable to find instrumentation info for: " + className);
19845 return false;
19846 }
19847 if (ai == null) {
19848 reportStartInstrumentationFailureLocked(watcher, className,
19849 "Unable to find instrumentation target package: " + ii.targetPackage);
19850 return false;
19851 }
19852 if (!ai.hasCode()) {
19853 reportStartInstrumentationFailureLocked(watcher, className,
19854 "Instrumentation target has no code: " + ii.targetPackage);
19855 return false;
19856 }
19857
19858 int match = mContext.getPackageManager().checkSignatures(
19859 ii.targetPackage, ii.packageName);
19860 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
19861 String msg = "Permission Denial: starting instrumentation "
19862 + className + " from pid="
19863 + Binder.getCallingPid()
19864 + ", uid=" + Binder.getCallingPid()
19865 + " not allowed because package " + ii.packageName
19866 + " does not have a signature matching the target "
19867 + ii.targetPackage;
19868 reportStartInstrumentationFailureLocked(watcher, className, msg);
19869 throw new SecurityException(msg);
19870 }
19871
19872 ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
19873 activeInstr.mClass = className;
19874 String defProcess = ai.processName;;
19875 if (ii.targetProcesses == null) {
19876 activeInstr.mTargetProcesses = new String[]{ai.processName};
19877 } else if (ii.targetProcesses.equals("*")) {
19878 activeInstr.mTargetProcesses = new String[0];
19879 } else {
19880 activeInstr.mTargetProcesses = ii.targetProcesses.split(",");
19881 defProcess = activeInstr.mTargetProcesses[0];
19882 }
19883 activeInstr.mTargetInfo = ai;
19884 activeInstr.mProfileFile = profileFile;
19885 activeInstr.mArguments = arguments;
19886 activeInstr.mWatcher = watcher;
19887 activeInstr.mUiAutomationConnection = uiAutomationConnection;
19888 activeInstr.mResultClass = className;
19889
19890 final long origId = Binder.clearCallingIdentity();
19891 // Instrumentation can kill and relaunch even persistent processes
19892 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId,
19893 "start instr");
19894 ProcessRecord app = addAppLocked(ai, defProcess, false, abiOverride);
19895 app.instr = activeInstr;
19896 activeInstr.mFinished = false;
19897 activeInstr.mRunningProcesses.add(app);
19898 if (!mActiveInstrumentation.contains(activeInstr)) {
19899 mActiveInstrumentation.add(activeInstr);
19900 }
19901 Binder.restoreCallingIdentity(origId);
19902 }
19903
19904 return true;
19905 }
19906
19907 /**
19908 * Report errors that occur while attempting to start Instrumentation. Always writes the
19909 * error to the logs, but if somebody is watching, send the report there too. This enables
19910 * the "am" command to report errors with more information.
19911 *
19912 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
19913 * @param cn The component name of the instrumentation.
19914 * @param report The error report.
19915 */
19916 private void reportStartInstrumentationFailureLocked(IInstrumentationWatcher watcher,
19917 ComponentName cn, String report) {
19918 Slog.w(TAG, report);
19919 if (watcher != null) {
19920 Bundle results = new Bundle();
19921 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
19922 results.putString("Error", report);
19923 mInstrumentationReporter.reportStatus(watcher, cn, -1, results);
19924 }
19925 }
19926
19927 void addInstrumentationResultsLocked(ProcessRecord app, Bundle results) {
19928 if (app.instr == null) {
19929 Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
19930 return;
19931 }
19932
19933 if (!app.instr.mFinished && results != null) {
19934 if (app.instr.mCurResults == null) {
19935 app.instr.mCurResults = new Bundle(results);
19936 } else {
19937 app.instr.mCurResults.putAll(results);
19938 }
19939 }
19940 }
19941
19942 public void addInstrumentationResults(IApplicationThread target, Bundle results) {
19943 int userId = UserHandle.getCallingUserId();
19944 // Refuse possible leaked file descriptors
19945 if (results != null && results.hasFileDescriptors()) {
19946 throw new IllegalArgumentException("File descriptors passed in Intent");
19947 }
19948
19949 synchronized(this) {
19950 ProcessRecord app = getRecordForAppLocked(target);
19951 if (app == null) {
19952 Slog.w(TAG, "addInstrumentationResults: no app for " + target);
19953 return;
19954 }
19955 final long origId = Binder.clearCallingIdentity();
19956 addInstrumentationResultsLocked(app, results);
19957 Binder.restoreCallingIdentity(origId);
19958 }
19959 }
19960
19961 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
19962 if (app.instr == null) {
19963 Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
19964 return;
19965 }
19966
19967 if (!app.instr.mFinished) {
19968 if (app.instr.mWatcher != null) {
19969 Bundle finalResults = app.instr.mCurResults;
19970 if (finalResults != null) {
19971 if (app.instr.mCurResults != null && results != null) {
19972 finalResults.putAll(results);
19973 }
19974 } else {
19975 finalResults = results;
19976 }
19977 mInstrumentationReporter.reportFinished(app.instr.mWatcher,
19978 app.instr.mClass, resultCode, finalResults);
19979 }
19980
19981 // Can't call out of the system process with a lock held, so post a message.
19982 if (app.instr.mUiAutomationConnection != null) {
19983 mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
19984 app.instr.mUiAutomationConnection).sendToTarget();
19985 }
19986 app.instr.mFinished = true;
19987 }
19988
19989 app.instr.removeProcess(app);
19990 app.instr = null;
19991
19992 forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false, app.userId,
19993 "finished inst");
19994 }
19995
19996 public void finishInstrumentation(IApplicationThread target,
19997 int resultCode, Bundle results) {
19998 int userId = UserHandle.getCallingUserId();
19999 // Refuse possible leaked file descriptors
20000 if (results != null && results.hasFileDescriptors()) {
20001 throw new IllegalArgumentException("File descriptors passed in Intent");
20002 }
20003
20004 synchronized(this) {
20005 ProcessRecord app = getRecordForAppLocked(target);
20006 if (app == null) {
20007 Slog.w(TAG, "finishInstrumentation: no app for " + target);
20008 return;
20009 }
20010 final long origId = Binder.clearCallingIdentity();
20011 finishInstrumentationLocked(app, resultCode, results);
20012 Binder.restoreCallingIdentity(origId);
20013 }
20014 }

配置相关

 20015
20016 // =========================================================
20017 // CONFIGURATION
20018 // =========================================================
20019
20020 public ConfigurationInfo getDeviceConfigurationInfo() {
20021 ConfigurationInfo config = new ConfigurationInfo();
20022 synchronized (this) {
20023 final Configuration globalConfig = getGlobalConfiguration();
20024 config.reqTouchScreen = globalConfig.touchscreen;
20025 config.reqKeyboardType = globalConfig.keyboard;
20026 config.reqNavigation = globalConfig.navigation;
20027 if (globalConfig.navigation == Configuration.NAVIGATION_DPAD
20028 || globalConfig.navigation == Configuration.NAVIGATION_TRACKBALL) {
20029 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
20030 }
20031 if (globalConfig.keyboard != Configuration.KEYBOARD_UNDEFINED
20032 && globalConfig.keyboard != Configuration.KEYBOARD_NOKEYS) {
20033 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
20034 }
20035 config.reqGlEsVersion = GL_ES_VERSION;
20036 }
20037 return config;
20038 }
20039
20040 ActivityStack getFocusedStack() {
20041 return mStackSupervisor.getFocusedStack();
20042 }
20043
20044 @Override
20045 public int getFocusedStackId() throws RemoteException {
20046 ActivityStack focusedStack = getFocusedStack();
20047 if (focusedStack != null) {
20048 return focusedStack.getStackId();
20049 }
20050 return -1;
20051 }
20052
20053 public Configuration getConfiguration() {
20054 Configuration ci;
20055 synchronized(this) {
20056 ci = new Configuration(getGlobalConfiguration());
20057 ci.userSetLocale = false;
20058 }
20059 return ci;
20060 }
20061
20062 @Override
20063 public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
20064 enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
20065 synchronized (this) {
20066 mSuppressResizeConfigChanges = suppress;
20067 }
20068 }
20069
20070 /**
20071 * NOTE: For the pinned stack, this method is usually called after the bounds animation has
20072 * animated the stack to the fullscreen, but can also be called if we are relaunching an
20073 * activity and clearing the task at the same time.
20074 */
20075 @Override
20076 public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
20077 enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
20078 if (StackId.isHomeOrRecentsStack(fromStackId)) {
20079 throw new IllegalArgumentException("You can't move tasks from the home/recents stack.");
20080 }
20081 synchronized (this) {
20082 final long origId = Binder.clearCallingIdentity();
20083 try {
20084 mStackSupervisor.moveTasksToFullscreenStackLocked(fromStackId, onTop);
20085 } finally {
20086 Binder.restoreCallingIdentity(origId);
20087 }
20088 }
20089 }
20090
20091 @Override
20092 public void updatePersistentConfiguration(Configuration values) {
20093 enforceCallingPermission(CHANGE_CONFIGURATION, "updatePersistentConfiguration()");
20094 enforceWriteSettingsPermission("updatePersistentConfiguration()");
20095 if (values == null) {
20096 throw new NullPointerException("Configuration must not be null");
20097 }
20098
20099 int userId = UserHandle.getCallingUserId();
20100
20101 synchronized(this) {
20102 updatePersistentConfigurationLocked(values, userId);
20103 }
20104 }
20105
20106 private void updatePersistentConfigurationLocked(Configuration values, @UserIdInt int userId) {
20107 final long origId = Binder.clearCallingIdentity();
20108 try {
20109 updateConfigurationLocked(values, null, false, true, userId, false /* deferResume */);
20110 } finally {
20111 Binder.restoreCallingIdentity(origId);
20112 }
20113 }
20114
20115 private void updateFontScaleIfNeeded(@UserIdInt int userId) {
20116 final float scaleFactor = Settings.System.getFloatForUser(mContext.getContentResolver(),
20117 FONT_SCALE, 1.0f, userId);
20118
20119 synchronized (this) {
20120 if (getGlobalConfiguration().fontScale == scaleFactor) {
20121 return;
20122 }
20123
20124 final Configuration configuration
20125 = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
20126 configuration.fontScale = scaleFactor;
20127 updatePersistentConfigurationLocked(configuration, userId);
20128 }
20129 }
20130
20131 private void enforceWriteSettingsPermission(String func) {
20132 int uid = Binder.getCallingUid();
20133 if (uid == ROOT_UID) {
20134 return;
20135 }
20136
20137 if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid,
20138 Settings.getPackageNameForUid(mContext, uid), false)) {
20139 return;
20140 }
20141
20142 String msg = "Permission Denial: " + func + " from pid="
20143 + Binder.getCallingPid()
20144 + ", uid=" + uid
20145 + " requires " + android.Manifest.permission.WRITE_SETTINGS;
20146 Slog.w(TAG, msg);
20147 throw new SecurityException(msg);
20148 }
20149
20150 @Override
20151 public boolean updateConfiguration(Configuration values) {
20152 enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
20153
20154 synchronized(this) {
20155 if (values == null && mWindowManager != null) {
20156 // sentinel: fetch the current configuration from the window manager
20157 values = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
20158 }
20159
20160 if (mWindowManager != null) {
20161 // Update OOM levels based on display size.
20162 mProcessList.applyDisplaySize(mWindowManager);
20163 }
20164
20165 final long origId = Binder.clearCallingIdentity();
20166 try {
20167 if (values != null) {
20168 Settings.System.clearConfiguration(values);
20169 }
20170 updateConfigurationLocked(values, null, false, false /* persistent */,
20171 UserHandle.USER_NULL, false /* deferResume */,
20172 mTmpUpdateConfigurationResult);
20173 return mTmpUpdateConfigurationResult.changes != 0;
20174 } finally {
20175 Binder.restoreCallingIdentity(origId);
20176 }
20177 }
20178 }
20179
20180 void updateUserConfigurationLocked() {
20181 final Configuration configuration = new Configuration(getGlobalConfiguration());
20182 final int currentUserId = mUserController.getCurrentUserIdLocked();
20183 Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
20184 currentUserId, Settings.System.canWrite(mContext));
20185 updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */,
20186 false /* persistent */, currentUserId, false /* deferResume */);
20187 }
20188
20189 boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
20190 boolean initLocale) {
20191 return updateConfigurationLocked(values, starting, initLocale, false /* deferResume */);
20192 }
20193
20194 boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
20195 boolean initLocale, boolean deferResume) {
20196 // pass UserHandle.USER_NULL as userId because we don't persist configuration for any user
20197 return updateConfigurationLocked(values, starting, initLocale, false /* persistent */,
20198 UserHandle.USER_NULL, deferResume);
20199 }
20200
20201 // To cache the list of supported system locales
20202 private String[] mSupportedSystemLocales = null;
20203
20204 private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
20205 boolean initLocale, boolean persistent, int userId, boolean deferResume) {
20206 return updateConfigurationLocked(values, starting, initLocale, persistent, userId,
20207 deferResume, null /* result */);
20208 }
20209
20210 /**
20211 * Do either or both things: (1) change the current configuration, and (2)
20212 * make sure the given activity is running with the (now) current
20213 * configuration. Returns true if the activity has been left running, or
20214 * false if <var>starting</var> is being destroyed to match the new
20215 * configuration.
20216 *
20217 * @param userId is only used when persistent parameter is set to true to persist configuration
20218 * for that particular user
20219 */
20220 private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
20221 boolean initLocale, boolean persistent, int userId, boolean deferResume,
20222 UpdateConfigurationResult result) {
20223 int changes = 0;
20224 boolean kept = true;
20225
20226 if (mWindowManager != null) {
20227 mWindowManager.deferSurfaceLayout();
20228 }
20229 try {
20230 if (values != null) {
20231 changes = updateGlobalConfiguration(values, initLocale, persistent, userId,
20232 deferResume);
20233 }
20234
20235 kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
20236 } finally {
20237 if (mWindowManager != null) {
20238 mWindowManager.continueSurfaceLayout();
20239 }
20240 }
20241
20242 if (result != null) {
20243 result.changes = changes;
20244 result.activityRelaunched = !kept;
20245 }
20246 return kept;
20247 }
20248
20249 /** Update default (global) configuration and notify listeners about changes. */
20250 private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
20251 boolean persistent, int userId, boolean deferResume) {
20252 mTempConfig.setTo(getGlobalConfiguration());
20253 final int changes = mTempConfig.updateFrom(values);
20254 if (changes == 0) {
20255 // Since calling to Activity.setRequestedOrientation leads to freezing the window with
20256 // setting WindowManagerService.mWaitingForConfig to true, it is important that we call
20257 // performDisplayOverrideConfigUpdate in order to send the new display configuration
20258 // (even if there are no actual changes) to unfreeze the window.
20259 performDisplayOverrideConfigUpdate(values, deferResume, DEFAULT_DISPLAY);
20260 return 0;
20261 }
20262
20263 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION,
20264 "Updating global configuration to: " + values);
20265
20266 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
20267
20268 if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) {
20269 final LocaleList locales = values.getLocales();
20270 int bestLocaleIndex = 0;
20271 if (locales.size() > 1) {
20272 if (mSupportedSystemLocales == null) {
20273 mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales();
20274 }
20275 bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales));
20276 }
20277 SystemProperties.set("persist.sys.locale",
20278 locales.get(bestLocaleIndex).toLanguageTag());
20279 LocaleList.setDefault(locales, bestLocaleIndex);
20280 mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG,
20281 locales.get(bestLocaleIndex)));
20282 }
20283
20284 mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
20285 mTempConfig.seq = mConfigurationSeq;
20286
20287 // Update stored global config and notify everyone about the change.
20288 mStackSupervisor.onConfigurationChanged(mTempConfig);
20289
20290 Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
20291 // TODO(multi-display): Update UsageEvents#Event to include displayId.
20292 mUsageStatsService.reportConfigurationChange(mTempConfig,
20293 mUserController.getCurrentUserIdLocked());
20294
20295 // TODO: If our config changes, should we auto dismiss any currently showing dialogs?
20296 mShowDialogs = shouldShowDialogs(mTempConfig);
20297
20298 AttributeCache ac = AttributeCache.instance();
20299 if (ac != null) {
20300 ac.updateConfiguration(mTempConfig);
20301 }
20302
20303 // Make sure all resources in our process are updated right now, so that anyone who is going
20304 // to retrieve resource values after we return will be sure to get the new ones. This is
20305 // especially important during boot, where the first config change needs to guarantee all
20306 // resources have that config before following boot code is executed.
20307 mSystemThread.applyConfigurationToResources(mTempConfig);
20308
20309 // We need another copy of global config because we're scheduling some calls instead of
20310 // running them in place. We need to be sure that object we send will be handled unchanged.
20311 final Configuration configCopy = new Configuration(mTempConfig);
20312 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
20313 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
20314 msg.obj = configCopy;
20315 msg.arg1 = userId;
20316 mHandler.sendMessage(msg);
20317 }
20318
20319 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
20320 ProcessRecord app = mLruProcesses.get(i);
20321 try {
20322 if (app.thread != null) {
20323 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
20324 + app.processName + " new config " + configCopy);
20325 app.thread.scheduleConfigurationChanged(configCopy);
20326 }
20327 } catch (Exception e) {
20328 }
20329 }
20330
20331 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
20332 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING
20333 | Intent.FLAG_RECEIVER_FOREGROUND
20334 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
20335 broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
20336 AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
20337 UserHandle.USER_ALL);
20338 if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
20339 intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
20340 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
20341 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
20342 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
20343 if (initLocale || !mProcessesReady) {
20344 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
20345 }
20346 broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
20347 AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
20348 UserHandle.USER_ALL);
20349 }
20350
20351 // Override configuration of the default display duplicates global config, so we need to
20352 // update it also. This will also notify WindowManager about changes.
20353 performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
20354 DEFAULT_DISPLAY);
20355
20356 return changes;
20357 }
20358
20359 @Override
20360 public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
20361 enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
20362
20363 synchronized (this) {
20364 // Check if display is initialized in AM.
20365 if (!mStackSupervisor.isDisplayAdded(displayId)) {
20366 // Call might come when display is not yet added or has already been removed.
20367 if (DEBUG_CONFIGURATION) {
20368 Slog.w(TAG, "Trying to update display configuration for non-existing displayId="
20369 + displayId);
20370 }
20371 return false;
20372 }
20373
20374 if (values == null && mWindowManager != null) {
20375 // sentinel: fetch the current configuration from the window manager
20376 values = mWindowManager.computeNewConfiguration(displayId);
20377 }
20378
20379 if (mWindowManager != null) {
20380 // Update OOM levels based on display size.
20381 mProcessList.applyDisplaySize(mWindowManager);
20382 }
20383
20384 final long origId = Binder.clearCallingIdentity();
20385 try {
20386 if (values != null) {
20387 Settings.System.clearConfiguration(values);
20388 }
20389 updateDisplayOverrideConfigurationLocked(values, null /* starting */,
20390 false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
20391 return mTmpUpdateConfigurationResult.changes != 0;
20392 } finally {
20393 Binder.restoreCallingIdentity(origId);
20394 }
20395 }
20396 }
20397
20398 boolean updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting,
20399 boolean deferResume, int displayId) {
20400 return updateDisplayOverrideConfigurationLocked(values, starting, deferResume /* deferResume */,
20401 displayId, null /* result */);
20402 }
20403
20404 /**
20405 * Updates override configuration specific for the selected display. If no config is provided,
20406 * new one will be computed in WM based on current display info.
20407 */
20408 private boolean updateDisplayOverrideConfigurationLocked(Configuration values,
20409 ActivityRecord starting, boolean deferResume, int displayId,
20410 UpdateConfigurationResult result) {
20411 int changes = 0;
20412 boolean kept = true;
20413
20414 if (mWindowManager != null) {
20415 mWindowManager.deferSurfaceLayout();
20416 }
20417 try {
20418 if (values != null) {
20419 if (displayId == DEFAULT_DISPLAY) {
20420 // Override configuration of the default display duplicates global config, so
20421 // we're calling global config update instead for default display. It will also
20422 // apply the correct override config.
20423 changes = updateGlobalConfiguration(values, false /* initLocale */,
20424 false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
20425 } else {
20426 changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
20427 }
20428 }
20429
20430 kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
20431 } finally {
20432 if (mWindowManager != null) {
20433 mWindowManager.continueSurfaceLayout();
20434 }
20435 }
20436
20437 if (result != null) {
20438 result.changes = changes;
20439 result.activityRelaunched = !kept;
20440 }
20441 return kept;
20442 }
20443
20444 private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
20445 int displayId) {
20446 mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
20447 final int changes = mTempConfig.updateFrom(values);
20448 if (changes != 0) {
20449 Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
20450 + mTempConfig + " for displayId=" + displayId);
20451 mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
20452
20453 final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
20454 if (isDensityChange && displayId == DEFAULT_DISPLAY) {
20455 // Reset the unsupported display size dialog.
20456 mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
20457
20458 killAllBackgroundProcessesExcept(N,
20459 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
20460 }
20461 }
20462
20463 // Update the configuration with WM first and check if any of the stacks need to be resized
20464 // due to the configuration change. If so, resize the stacks now and do any relaunches if
20465 // necessary. This way we don't need to relaunch again afterwards in
20466 // ensureActivityConfigurationLocked().
20467 if (mWindowManager != null) {
20468 final int[] resizedStacks =
20469 mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
20470 if (resizedStacks != null) {
20471 for (int stackId : resizedStacks) {
20472 resizeStackWithBoundsFromWindowManager(stackId, deferResume);
20473 }
20474 }
20475 }
20476
20477 return changes;
20478 }
20479
20480 /** Applies latest configuration and/or visibility updates if needed. */
20481 private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
20482 boolean kept = true;
20483 final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
20484 // mainStack is null during startup.
20485 if (mainStack != null) {
20486 if (changes != 0 && starting == null) {
20487 // If the configuration changed, and the caller is not already
20488 // in the process of starting an activity, then find the top
20489 // activity to check if its configuration needs to change.
20490 starting = mainStack.topRunningActivityLocked();
20491 }
20492
20493 if (starting != null) {
20494 kept = starting.ensureActivityConfigurationLocked(changes,
20495 false /* preserveWindow */);
20496 // And we need to make sure at this point that all other activities
20497 // are made visible with the correct configuration.
20498 mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
20499 !PRESERVE_WINDOWS);
20500 }
20501 }
20502
20503 return kept;
20504 }
20505
20506 /** Helper method that requests bounds from WM and applies them to stack. */
20507 private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
20508 final Rect newStackBounds = new Rect();
20509 mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds);
20510 mStackSupervisor.resizeStackLocked(
20511 stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
20512 null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
20513 false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
20514 }
20515
20516 /**
20517 * Decide based on the configuration whether we should show the ANR,
20518 * crash, etc dialogs. The idea is that if there is no affordance to
20519 * press the on-screen buttons, or the user experience would be more
20520 * greatly impacted than the crash itself, we shouldn't show the dialog.
20521 *
20522 * A thought: SystemUI might also want to get told about this, the Power
20523 * dialog / global actions also might want different behaviors.
20524 */
20525 private static boolean shouldShowDialogs(Configuration config) {
20526 final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS
20527 && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
20528 && config.navigation == Configuration.NAVIGATION_NONAV);
20529 int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
20530 final boolean uiModeSupportsDialogs = (modeType != Configuration.UI_MODE_TYPE_CAR
20531 && !(modeType == Configuration.UI_MODE_TYPE_WATCH && "user".equals(Build.TYPE))
20532 && modeType != Configuration.UI_MODE_TYPE_TELEVISION
20533 && modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
20534 return inputMethodExists && uiModeSupportsDialogs;
20535 }
20536
20537 @Override
20538 public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
20539 synchronized (this) {
20540 ActivityRecord srec = ActivityRecord.forTokenLocked(token);
20541 if (srec != null) {
20542 return srec.getStack().shouldUpRecreateTaskLocked(srec, destAffinity);
20543 }
20544 }
20545 return false;
20546 }
20547
20548 public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
20549 Intent resultData) {
20550
20551 synchronized (this) {
20552 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
20553 if (r != null) {
20554 return r.getStack().navigateUpToLocked(r, destIntent, resultCode, resultData);
20555 }
20556 return false;
20557 }
20558 }
20559
20560 public int getLaunchedFromUid(IBinder activityToken) {
20561 ActivityRecord srec;
20562 synchronized (this) {
20563 srec = ActivityRecord.forTokenLocked(activityToken);
20564 }
20565 if (srec == null) {
20566 return -1;
20567 }
20568 return srec.launchedFromUid;
20569 }
20570
20571 public String getLaunchedFromPackage(IBinder activityToken) {
20572 ActivityRecord srec;
20573 synchronized (this) {
20574 srec = ActivityRecord.forTokenLocked(activityToken);
20575 }
20576 if (srec == null) {
20577 return null;
20578 }
20579 return srec.launchedFromPackage;
20580 }
20581

管理app生命周期

 20582    // =========================================================
20583 // LIFETIME MANAGEMENT
20584 // =========================================================
20585
20586 // Returns whether the app is receiving broadcast.
20587 // If receiving, fetch all broadcast queues which the app is
20588 // the current [or imminent] receiver on.
20589 private boolean isReceivingBroadcastLocked(ProcessRecord app,
20590 ArraySet<BroadcastQueue> receivingQueues) {
20591 if (!app.curReceivers.isEmpty()) {
20592 for (BroadcastRecord r : app.curReceivers) {
20593 receivingQueues.add(r.queue);
20594 }
20595 return true;
20596 }
20597
20598 // It's not the current receiver, but it might be starting up to become one
20599 for (BroadcastQueue queue : mBroadcastQueues) {
20600 final BroadcastRecord r = queue.mPendingBroadcast;
20601 if (r != null && r.curApp == app) {
20602 // found it; report which queue it's in
20603 receivingQueues.add(queue);
20604 }
20605 }
20606
20607 return !receivingQueues.isEmpty();
20608 }
20609
20610 Association startAssociationLocked(int sourceUid, String sourceProcess, int sourceState,
20611 int targetUid, ComponentName targetComponent, String targetProcess) {
20612 if (!mTrackingAssociations) {
20613 return null;
20614 }
20615 ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> components
20616 = mAssociations.get(targetUid);
20617 if (components == null) {
20618 components = new ArrayMap<>();
20619 mAssociations.put(targetUid, components);
20620 }
20621 SparseArray<ArrayMap<String, Association>> sourceUids = components.get(targetComponent);
20622 if (sourceUids == null) {
20623 sourceUids = new SparseArray<>();
20624 components.put(targetComponent, sourceUids);
20625 }
20626 ArrayMap<String, Association> sourceProcesses = sourceUids.get(sourceUid);
20627 if (sourceProcesses == null) {
20628 sourceProcesses = new ArrayMap<>();
20629 sourceUids.put(sourceUid, sourceProcesses);
20630 }
20631 Association ass = sourceProcesses.get(sourceProcess);
20632 if (ass == null) {
20633 ass = new Association(sourceUid, sourceProcess, targetUid, targetComponent,
20634 targetProcess);
20635 sourceProcesses.put(sourceProcess, ass);
20636 }
20637 ass.mCount++;
20638 ass.mNesting++;
20639 if (ass.mNesting == 1) {
20640 ass.mStartTime = ass.mLastStateUptime = SystemClock.uptimeMillis();
20641 ass.mLastState = sourceState;
20642 }
20643 return ass;
20644 }
20645
20646 void stopAssociationLocked(int sourceUid, String sourceProcess, int targetUid,
20647 ComponentName targetComponent) {
20648 if (!mTrackingAssociations) {
20649 return;
20650 }
20651 ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> components
20652 = mAssociations.get(targetUid);
20653 if (components == null) {
20654 return;
20655 }
20656 SparseArray<ArrayMap<String, Association>> sourceUids = components.get(targetComponent);
20657 if (sourceUids == null) {
20658 return;
20659 }
20660 ArrayMap<String, Association> sourceProcesses = sourceUids.get(sourceUid);
20661 if (sourceProcesses == null) {
20662 return;
20663 }
20664 Association ass = sourceProcesses.get(sourceProcess);
20665 if (ass == null || ass.mNesting <= 0) {
20666 return;
20667 }
20668 ass.mNesting--;
20669 if (ass.mNesting == 0) {
20670 long uptime = SystemClock.uptimeMillis();
20671 ass.mTime += uptime - ass.mStartTime;
20672 ass.mStateTimes[ass.mLastState-ActivityManager.MIN_PROCESS_STATE]
20673 += uptime - ass.mLastStateUptime;
20674 ass.mLastState = ActivityManager.MAX_PROCESS_STATE + 2;
20675 }
20676 }
20677
20678 private void noteUidProcessState(final int uid, final int state) {
20679 mBatteryStatsService.noteUidProcessState(uid, state);
20680 if (mTrackingAssociations) {
20681 for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) {
20682 ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents
20683 = mAssociations.valueAt(i1);
20684 for (int i2=0, N2=targetComponents.size(); i2<N2; i2++) {
20685 SparseArray<ArrayMap<String, Association>> sourceUids
20686 = targetComponents.valueAt(i2);
20687 ArrayMap<String, Association> sourceProcesses = sourceUids.get(uid);
20688 if (sourceProcesses != null) {
20689 for (int i4=0, N4=sourceProcesses.size(); i4<N4; i4++) {
20690 Association ass = sourceProcesses.valueAt(i4);
20691 if (ass.mNesting >= 1) {
20692 // currently associated
20693 long uptime = SystemClock.uptimeMillis();
20694 ass.mStateTimes[ass.mLastState-ActivityManager.MIN_PROCESS_STATE]
20695 += uptime - ass.mLastStateUptime;
20696 ass.mLastState = state;
20697 ass.mLastStateUptime = uptime;
20698 }
20699 }
20700 }
20701 }
20702 }
20703 }
20704 }
20705
20706 private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
20707 boolean doingAll, long now) {
20708 if (mAdjSeq == app.adjSeq) {
20709 // This adjustment has already been computed.
20710 return app.curRawAdj;
20711 }
20712
20713 if (app.thread == null) {
20714 app.adjSeq = mAdjSeq;
20715 app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
20716 app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
20717 return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
20718 }
20719
20720 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
20721 app.adjSource = null;
20722 app.adjTarget = null;
20723 app.empty = false;
20724 app.cached = false;
20725
20726 final int activitiesSize = app.activities.size();
20727
20728 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
20729 // The max adjustment doesn't allow this app to be anything
20730 // below foreground, so it is not worth doing work for it.
20731 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making fixed: " + app);
20732 app.adjType = "fixed";
20733 app.adjSeq = mAdjSeq;
20734 app.curRawAdj = app.maxAdj;
20735 app.foregroundActivities = false;
20736 app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20737 app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
20738 // System processes can do UI, and when they do we want to have
20739 // them trim their memory after the user leaves the UI. To
20740 // facilitate this, here we need to determine whether or not it
20741 // is currently showing UI.
20742 app.systemNoUi = true;
20743 if (app == TOP_APP) {
20744 app.systemNoUi = false;
20745 app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
20746 app.adjType = "pers-top-activity";
20747 } else if (app.hasTopUi) {
20748 app.systemNoUi = false;
20749 app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
20750 app.adjType = "pers-top-ui";
20751 } else if (activitiesSize > 0) {
20752 for (int j = 0; j < activitiesSize; j++) {
20753 final ActivityRecord r = app.activities.get(j);
20754 if (r.visible) {
20755 app.systemNoUi = false;
20756 }
20757 }
20758 }
20759 if (!app.systemNoUi) {
20760 app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
20761 }
20762 return (app.curAdj=app.maxAdj);
20763 }
20764
20765 app.systemNoUi = false;
20766
20767 final int PROCESS_STATE_CUR_TOP = mTopProcessState;
20768
20769 // Determine the importance of the process, starting with most
20770 // important to least, and assign an appropriate OOM adjustment.
20771 int adj;
20772 int schedGroup;
20773 int procState;
20774 boolean foregroundActivities = false;
20775 mTmpBroadcastQueue.clear();
20776 if (app == TOP_APP) {
20777 // The last app on the list is the foreground app.
20778 adj = ProcessList.FOREGROUND_APP_ADJ;
20779 schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
20780 app.adjType = "top-activity";
20781 foregroundActivities = true;
20782 procState = PROCESS_STATE_CUR_TOP;
20783 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making top: " + app);
20784 } else if (app.instr != null) {
20785 // Don't want to kill running instrumentation.
20786 adj = ProcessList.FOREGROUND_APP_ADJ;
20787 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20788 app.adjType = "instrumentation";
20789 procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
20790 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making instrumentation: " + app);
20791 } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
20792 // An app that is currently receiving a broadcast also
20793 // counts as being in the foreground for OOM killer purposes.
20794 // It's placed in a sched group based on the nature of the
20795 // broadcast as reflected by which queue it's active in.
20796 adj = ProcessList.FOREGROUND_APP_ADJ;
20797 schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
20798 ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
20799 app.adjType = "broadcast";
20800 procState = ActivityManager.PROCESS_STATE_RECEIVER;
20801 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making broadcast: " + app);
20802 } else if (app.executingServices.size() > 0) {
20803 // An app that is currently executing a service callback also
20804 // counts as being in the foreground.
20805 adj = ProcessList.FOREGROUND_APP_ADJ;
20806 schedGroup = app.execServicesFg ?
20807 ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
20808 app.adjType = "exec-service";
20809 procState = ActivityManager.PROCESS_STATE_SERVICE;
20810 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making exec-service: " + app);
20811 //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
20812 } else {
20813 // As far as we know the process is empty. We may change our mind later.
20814 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
20815 // At this point we don't actually know the adjustment. Use the cached adj
20816 // value that the caller wants us to.
20817 adj = cachedAdj;
20818 procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
20819 app.cached = true;
20820 app.empty = true;
20821 app.adjType = "cch-empty";
20822 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making empty: " + app);
20823 }
20824
20825 // Examine all activities if not already foreground.
20826 if (!foregroundActivities && activitiesSize > 0) {
20827 int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
20828 for (int j = 0; j < activitiesSize; j++) {
20829 final ActivityRecord r = app.activities.get(j);
20830 if (r.app != app) {
20831 Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app
20832 + " instead of expected " + app);
20833 if (r.app == null || (r.app.uid == app.uid)) {
20834 // Only fix things up when they look sane
20835 r.app = app;
20836 } else {
20837 continue;
20838 }
20839 }
20840 if (r.visible) {
20841 // App has a visible activity; only upgrade adjustment.
20842 if (adj > ProcessList.VISIBLE_APP_ADJ) {
20843 adj = ProcessList.VISIBLE_APP_ADJ;
20844 app.adjType = "vis-activity";
20845 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
20846 }
20847 if (procState > PROCESS_STATE_CUR_TOP) {
20848 procState = PROCESS_STATE_CUR_TOP;
20849 app.adjType = "vis-activity";
20850 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
20851 }
20852 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20853 app.cached = false;
20854 app.empty = false;
20855 foregroundActivities = true;
20856 final TaskRecord task = r.getTask();
20857 if (task != null && minLayer > 0) {
20858 final int layer = task.mLayerRank;
20859 if (layer >= 0 && minLayer > layer) {
20860 minLayer = layer;
20861 }
20862 }
20863 break;
20864 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
20865 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
20866 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
20867 app.adjType = "pause-activity";
20868 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
20869 }
20870 if (procState > PROCESS_STATE_CUR_TOP) {
20871 procState = PROCESS_STATE_CUR_TOP;
20872 app.adjType = "pause-activity";
20873 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
20874 }
20875 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20876 app.cached = false;
20877 app.empty = false;
20878 foregroundActivities = true;
20879 } else if (r.state == ActivityState.STOPPING) {
20880 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
20881 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
20882 app.adjType = "stop-activity";
20883 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
20884 }
20885 // For the process state, we will at this point consider the
20886 // process to be cached. It will be cached either as an activity
20887 // or empty depending on whether the activity is finishing. We do
20888 // this so that we can treat the process as cached for purposes of
20889 // memory trimming (determing current memory level, trim command to
20890 // send to process) since there can be an arbitrary number of stopping
20891 // processes and they should soon all go into the cached state.
20892 if (!r.finishing) {
20893 if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
20894 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
20895 app.adjType = "stop-activity";
20896 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
20897 }
20898 }
20899 app.cached = false;
20900 app.empty = false;
20901 foregroundActivities = true;
20902 } else {
20903 if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
20904 procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
20905 app.adjType = "cch-act";
20906 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to cached activity: " + app);
20907 }
20908 }
20909 }
20910 if (adj == ProcessList.VISIBLE_APP_ADJ) {
20911 adj += minLayer;
20912 }
20913 }
20914
20915 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
20916 || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
20917 if (app.foregroundServices) {
20918 // The user is aware of this app, so make it visible.
20919 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
20920 procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
20921 app.cached = false;
20922 app.adjType = "fg-service";
20923 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20924 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to fg service: " + app);
20925 } else if (app.hasOverlayUi) {
20926 // The process is display an overlay UI.
20927 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
20928 procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
20929 app.cached = false;
20930 app.adjType = "has-overlay-ui";
20931 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20932 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to overlay ui: " + app);
20933 }
20934 }
20935
20936 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
20937 || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
20938 if (app.forcingToImportant != null) {
20939 // This is currently used for toasts... they are not interactive, and
20940 // we don't want them to cause the app to become fully foreground (and
20941 // thus out of background check), so we yes the best background level we can.
20942 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
20943 procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
20944 app.cached = false;
20945 app.adjType = "force-imp";
20946 app.adjSource = app.forcingToImportant;
20947 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
20948 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to force imp: " + app);
20949 }
20950 }
20951
20952 if (app == mHeavyWeightProcess) {
20953 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
20954 // We don't want to kill the current heavy-weight process.
20955 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
20956 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
20957 app.cached = false;
20958 app.adjType = "heavy";
20959 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
20960 }
20961 if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
20962 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
20963 app.adjType = "heavy";
20964 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
20965 }
20966 }
20967
20968 if (app == mHomeProcess) {
20969 if (adj > ProcessList.HOME_APP_ADJ) {
20970 // This process is hosting what we currently consider to be the
20971 // home app, so we don't want to let it go into the background.
20972 adj = ProcessList.HOME_APP_ADJ;
20973 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
20974 app.cached = false;
20975 app.adjType = "home";
20976 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
20977 }
20978 if (procState > ActivityManager.PROCESS_STATE_HOME) {
20979 procState = ActivityManager.PROCESS_STATE_HOME;
20980 app.adjType = "home";
20981 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
20982 }
20983 }
20984
20985 if (app == mPreviousProcess && app.activities.size() > 0) {
20986 if (adj > ProcessList.PREVIOUS_APP_ADJ) {
20987 // This was the previous process that showed UI to the user.
20988 // We want to try to keep it around more aggressively, to give
20989 // a good experience around switching between two apps.
20990 adj = ProcessList.PREVIOUS_APP_ADJ;
20991 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
20992 app.cached = false;
20993 app.adjType = "previous";
20994 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
20995 }
20996 if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
20997 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
20998 app.adjType = "previous";
20999 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
21000 }
21001 }
21002
21003 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
21004 + " reason=" + app.adjType);
21005
21006 // By default, we use the computed adjustment. It may be changed if
21007 // there are applications dependent on our services or providers, but
21008 // this gives us a baseline and makes sure we don't get into an
21009 // infinite recursion.
21010 app.adjSeq = mAdjSeq;
21011 app.curRawAdj = adj;
21012 app.hasStartedServices = false;
21013
21014 if (mBackupTarget != null && app == mBackupTarget.app) {
21015 // If possible we want to avoid killing apps while they're being backed up
21016 if (adj > ProcessList.BACKUP_APP_ADJ) {
21017 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
21018 adj = ProcessList.BACKUP_APP_ADJ;
21019 if (procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
21020 procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
21021 }
21022 app.adjType = "backup";
21023 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
21024 app.cached = false;
21025 }
21026 if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
21027 procState = ActivityManager.PROCESS_STATE_BACKUP;
21028 app.adjType = "backup";
21029 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
21030 }
21031 }
21032
21033 boolean mayBeTop = false;
21034 String mayBeTopType = null;
21035 Object mayBeTopSource = null;
21036 Object mayBeTopTarget = null;
21037
21038 for (int is = app.services.size()-1;
21039 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
21040 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
21041 || procState > ActivityManager.PROCESS_STATE_TOP);
21042 is--) {
21043 ServiceRecord s = app.services.valueAt(is);
21044 if (s.startRequested) {
21045 app.hasStartedServices = true;
21046 if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
21047 procState = ActivityManager.PROCESS_STATE_SERVICE;
21048 app.adjType = "started-services";
21049 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
21050 }
21051 if (app.hasShownUi && app != mHomeProcess) {
21052 // If this process has shown some UI, let it immediately
21053 // go to the LRU list because it may be pretty heavy with
21054 // UI stuff. We'll tag it with a label just to help
21055 // debug and understand what is going on.
21056 if (adj > ProcessList.SERVICE_ADJ) {
21057 app.adjType = "cch-started-ui-services";
21058 }
21059 } else {
21060 if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
21061 // This service has seen some activity within
21062 // recent memory, so we will keep its process ahead
21063 // of the background processes.
21064 if (adj > ProcessList.SERVICE_ADJ) {
21065 adj = ProcessList.SERVICE_ADJ;
21066 app.adjType = "started-services";
21067 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
21068 app.cached = false;
21069 }
21070 }
21071 // If we have let the service slide into the background
21072 // state, still have some text describing what it is doing
21073 // even though the service no longer has an impact.
21074 if (adj > ProcessList.SERVICE_ADJ) {
21075 app.adjType = "cch-started-services";
21076 }
21077 }
21078 }
21079
21080 for (int conni = s.connections.size()-1;
21081 conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
21082 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
21083 || procState > ActivityManager.PROCESS_STATE_TOP);
21084 conni--) {
21085 ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
21086 for (int i = 0;
21087 i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
21088 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
21089 || procState > ActivityManager.PROCESS_STATE_TOP);
21090 i++) {
21091 // XXX should compute this based on the max of
21092 // all connected clients.
21093 ConnectionRecord cr = clist.get(i);
21094 if (cr.binding.client == app) {
21095 // Binding to ourself is not interesting.
21096 continue;
21097 }
21098
21099 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
21100 ProcessRecord client = cr.binding.client;
21101 int clientAdj = computeOomAdjLocked(client, cachedAdj,
21102 TOP_APP, doingAll, now);
21103 int clientProcState = client.curProcState;
21104 if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
21105 // If the other app is cached for any reason, for purposes here
21106 // we are going to consider it empty. The specific cached state
21107 // doesn't propagate except under certain conditions.
21108 clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
21109 }
21110 String adjType = null;
21111 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
21112 // Not doing bind OOM management, so treat
21113 // this guy more like a started service.
21114 if (app.hasShownUi && app != mHomeProcess) {
21115 // If this process has shown some UI, let it immediately
21116 // go to the LRU list because it may be pretty heavy with
21117 // UI stuff. We'll tag it with a label just to help
21118 // debug and understand what is going on.
21119 if (adj > clientAdj) {
21120 adjType = "cch-bound-ui-services";
21121 }
21122 app.cached = false;
21123 clientAdj = adj;
21124 clientProcState = procState;
21125 } else {
21126 if (now >= (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
21127 // This service has not seen activity within
21128 // recent memory, so allow it to drop to the
21129 // LRU list if there is no other reason to keep
21130 // it around. We'll also tag it with a label just
21131 // to help debug and undertand what is going on.
21132 if (adj > clientAdj) {
21133 adjType = "cch-bound-services";
21134 }
21135 clientAdj = adj;
21136 }
21137 }
21138 }
21139 if (adj > clientAdj) {
21140 // If this process has recently shown UI, and
21141 // the process that is binding to it is less
21142 // important than being visible, then we don't
21143 // care about the binding as much as we care
21144 // about letting this process get into the LRU
21145 // list to be killed and restarted if needed for
21146 // memory.
21147 if (app.hasShownUi && app != mHomeProcess
21148 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
21149 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
21150 adjType = "cch-bound-ui-services";
21151 }
21152 } else {
21153 int newAdj;
21154 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
21155 |Context.BIND_IMPORTANT)) != 0) {
21156 newAdj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
21157 ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
21158 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
21159 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
21160 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
21161 newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
21162 } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
21163 newAdj = clientAdj;
21164 } else {
21165 if (adj > ProcessList.VISIBLE_APP_ADJ) {
21166 newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
21167 } else {
21168 newAdj = adj;
21169 }
21170 }
21171 if (!client.cached) {
21172 app.cached = false;
21173 }
21174 if (adj > newAdj) {
21175 adj = newAdj;
21176 adjType = "service";
21177 }
21178 }
21179 }
21180 if ((cr.flags & (Context.BIND_NOT_FOREGROUND
21181 | Context.BIND_IMPORTANT_BACKGROUND)) == 0) {
21182 // This will treat important bound services identically to
21183 // the top app, which may behave differently than generic
21184 // foreground work.
21185 if (client.curSchedGroup > schedGroup) {
21186 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
21187 schedGroup = client.curSchedGroup;
21188 } else {
21189 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
21190 }
21191 }
21192 if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
21193 if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
21194 // Special handling of clients who are in the top state.
21195 // We *may* want to consider this process to be in the
21196 // top state as well, but only if there is not another
21197 // reason for it to be running. Being on the top is a
21198 // special state, meaning you are specifically running
21199 // for the current top app. If the process is already
21200 // running in the background for some other reason, it
21201 // is more important to continue considering it to be
21202 // in the background state.
21203 mayBeTop = true;
21204 mayBeTopType = "service";
21205 mayBeTopSource = cr.binding.client;
21206 mayBeTopTarget = s.name;
21207 clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
21208 } else {
21209 // Special handling for above-top states (persistent
21210 // processes). These should not bring the current process
21211 // into the top state, since they are not on top. Instead
21212 // give them the best state after that.
21213 if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
21214 clientProcState =
21215 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
21216 } else if (mWakefulness
21217 == PowerManagerInternal.WAKEFULNESS_AWAKE &&
21218 (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
21219 != 0) {
21220 clientProcState =
21221 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
21222 } else {
21223 clientProcState =
21224 ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
21225 }
21226 }
21227 }
21228 } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
21229 if (clientProcState <
21230 ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
21231 clientProcState =
21232 ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
21233 }
21234 } else {
21235 if (clientProcState <
21236 ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
21237 clientProcState =
21238 ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
21239 }
21240 }
21241 if (procState > clientProcState) {
21242 procState = clientProcState;
21243 if (adjType == null) {
21244 adjType = "service";
21245 }
21246 }
21247 if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
21248 && (cr.flags&Context.BIND_SHOWING_UI) != 0) {
21249 app.pendingUiClean = true;
21250 }
21251 if (adjType != null) {
21252 app.adjType = adjType;
21253 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
21254 .REASON_SERVICE_IN_USE;
21255 app.adjSource = cr.binding.client;
21256 app.adjSourceProcState = clientProcState;
21257 app.adjTarget = s.name;
21258 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
21259 + ": " + app + ", due to " + cr.binding.client
21260 + " adj=" + adj + " procState=" + procState);
21261 }
21262 }
21263 if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
21264 app.treatLikeActivity = true;
21265 }
21266 final ActivityRecord a = cr.activity;
21267 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
21268 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
21269 (a.visible || a.state == ActivityState.RESUMED ||
21270 a.state == ActivityState.PAUSING)) {
21271 adj = ProcessList.FOREGROUND_APP_ADJ;
21272 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
21273 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
21274 schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
21275 } else {
21276 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
21277 }
21278 }
21279 app.cached = false;
21280 app.adjType = "service";
21281 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
21282 .REASON_SERVICE_IN_USE;
21283 app.adjSource = a;
21284 app.adjSourceProcState = procState;
21285 app.adjTarget = s.name;
21286 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to service w/activity: "
21287 + app);
21288 }
21289 }
21290 }
21291 }
21292 }
21293
21294 for (int provi = app.pubProviders.size()-1;
21295 provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
21296 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
21297 || procState > ActivityManager.PROCESS_STATE_TOP);
21298 provi--) {
21299 ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
21300 for (int i = cpr.connections.size()-1;
21301 i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
21302 || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
21303 || procState > ActivityManager.PROCESS_STATE_TOP);
21304 i--) {
21305 ContentProviderConnection conn = cpr.connections.get(i);
21306 ProcessRecord client = conn.client;
21307 if (client == app) {
21308 // Being our own client is not interesting.
21309 continue;
21310 }
21311 int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
21312 int clientProcState = client.curProcState;
21313 if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
21314 // If the other app is cached for any reason, for purposes here
21315 // we are going to consider it empty.
21316 clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
21317 }
21318 String adjType = null;
21319 if (adj > clientAdj) {
21320 if (app.hasShownUi && app != mHomeProcess
21321 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
21322 adjType = "cch-ui-provider";
21323 } else {
21324 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
21325 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
21326 adjType = "provider";
21327 }
21328 app.cached &= client.cached;
21329 }
21330 if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
21331 if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
21332 // Special handling of clients who are in the top state.
21333 // We *may* want to consider this process to be in the
21334 // top state as well, but only if there is not another
21335 // reason for it to be running. Being on the top is a
21336 // special state, meaning you are specifically running
21337 // for the current top app. If the process is already
21338 // running in the background for some other reason, it
21339 // is more important to continue considering it to be
21340 // in the background state.
21341 mayBeTop = true;
21342 clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
21343 mayBeTopType = adjType = "provider-top";
21344 mayBeTopSource = client;
21345 mayBeTopTarget = cpr.name;
21346 } else {
21347 // Special handling for above-top states (persistent
21348 // processes). These should not bring the current process
21349 // into the top state, since they are not on top. Instead
21350 // give them the best state after that.
21351 clientProcState =
21352 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
21353 if (adjType == null) {
21354 adjType = "provider";
21355 }
21356 }
21357 }
21358 if (procState > clientProcState) {
21359 procState = clientProcState;
21360 }
21361 if (client.curSchedGroup > schedGroup) {
21362 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
21363 }
21364 if (adjType != null) {
21365 app.adjType = adjType;
21366 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
21367 .REASON_PROVIDER_IN_USE;
21368 app.adjSource = client;
21369 app.adjSourceProcState = clientProcState;
21370 app.adjTarget = cpr.name;
21371 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
21372 + ": " + app + ", due to " + client
21373 + " adj=" + adj + " procState=" + procState);
21374 }
21375 }
21376 // If the provider has external (non-framework) process
21377 // dependencies, ensure that its adjustment is at least
21378 // FOREGROUND_APP_ADJ.
21379 if (cpr.hasExternalProcessHandles()) {
21380 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
21381 adj = ProcessList.FOREGROUND_APP_ADJ;
21382 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
21383 app.cached = false;
21384 app.adjType = "ext-provider";
21385 app.adjTarget = cpr.name;
21386 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to external provider: " + app);
21387 }
21388 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
21389 procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
21390 }
21391 }
21392 }
21393
21394 if (app.lastProviderTime > 0 &&
21395 (app.lastProviderTime+mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
21396 if (adj > ProcessList.PREVIOUS_APP_ADJ) {
21397 adj = ProcessList.PREVIOUS_APP_ADJ;
21398 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
21399 app.cached = false;
21400 app.adjType = "recent-provider";
21401 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
21402 }
21403 if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
21404 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
21405 app.adjType = "recent-provider";
21406 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
21407 }
21408 }
21409
21410 if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {
21411 // A client of one of our services or providers is in the top state. We
21412 // *may* want to be in the top state, but not if we are already running in
21413 // the background for some other reason. For the decision here, we are going
21414 // to pick out a few specific states that we want to remain in when a client
21415 // is top (states that tend to be longer-term) and otherwise allow it to go
21416 // to the top state.
21417 switch (procState) {
21418 case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
21419 // Something else is keeping it at this level, just leave it.
21420 break;
21421 case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
21422 case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
21423 case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
21424 case ActivityManager.PROCESS_STATE_SERVICE:
21425 // These all are longer-term states, so pull them up to the top
21426 // of the background states, but not all the way to the top state.
21427 procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
21428 app.adjType = mayBeTopType;
21429 app.adjSource = mayBeTopSource;
21430 app.adjTarget = mayBeTopTarget;
21431 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
21432 + ": " + app + ", due to " + mayBeTopSource
21433 + " adj=" + adj + " procState=" + procState);
21434 break;
21435 default:
21436 // Otherwise, top is a better choice, so take it.
21437 procState = ActivityManager.PROCESS_STATE_TOP;
21438 app.adjType = mayBeTopType;
21439 app.adjSource = mayBeTopSource;
21440 app.adjTarget = mayBeTopTarget;
21441 if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
21442 + ": " + app + ", due to " + mayBeTopSource
21443 + " adj=" + adj + " procState=" + procState);
21444 break;
21445 }
21446 }
21447
21448 if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
21449 if (app.hasClientActivities) {
21450 // This is a cached process, but with client activities. Mark it so.
21451 procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
21452 app.adjType = "cch-client-act";
21453 } else if (app.treatLikeActivity) {
21454 // This is a cached process, but somebody wants us to treat it like it has
21455 // an activity, okay!
21456 procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
21457 app.adjType = "cch-as-act";
21458 }
21459 }
21460
21461 if (adj == ProcessList.SERVICE_ADJ) {
21462 if (doingAll) {
21463 app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
21464 mNewNumServiceProcs++;
21465 //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
21466 if (!app.serviceb) {
21467 // This service isn't far enough down on the LRU list to
21468 // normally be a B service, but if we are low on RAM and it
21469 // is large we want to force it down since we would prefer to
21470 // keep launcher over it.
21471 if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
21472 && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
21473 app.serviceHighRam = true;
21474 app.serviceb = true;
21475 //Slog.i(TAG, "ADJ " + app + " high ram!");
21476 } else {
21477 mNewNumAServiceProcs++;
21478 //Slog.i(TAG, "ADJ " + app + " not high ram!");
21479 }
21480 } else {
21481 app.serviceHighRam = false;
21482 }
21483 }
21484 if (app.serviceb) {
21485 adj = ProcessList.SERVICE_B_ADJ;
21486 }
21487 }
21488
21489 app.curRawAdj = adj;
21490
21491 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
21492 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
21493 if (adj > app.maxAdj) {
21494 adj = app.maxAdj;
21495 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
21496 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
21497 }
21498 }
21499
21500 // Do final modification to adj. Everything we do between here and applying
21501 // the final setAdj must be done in this function, because we will also use
21502 // it when computing the final cached adj later. Note that we don't need to
21503 // worry about this for max adj above, since max adj will always be used to
21504 // keep it out of the cached vaues.
21505 app.curAdj = app.modifyRawOomAdj(adj);
21506 app.curSchedGroup = schedGroup;
21507 app.curProcState = procState;
21508 app.foregroundActivities = foregroundActivities;
21509
21510 return app.curRawAdj;
21511 }
21512
21513 /**
21514 * Record new PSS sample for a process.
21515 */
21516 void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
21517 long now) {
21518 EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
21519 swapPss * 1024);
21520 proc.lastPssTime = now;
21521 proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
21522 if (DEBUG_PSS) Slog.d(TAG_PSS,
21523 "PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
21524 + " state=" + ProcessList.makeProcStateString(procState));
21525 if (proc.initialIdlePss == 0) {
21526 proc.initialIdlePss = pss;
21527 }
21528 proc.lastPss = pss;
21529 proc.lastSwapPss = swapPss;
21530 if (procState >= ActivityManager.PROCESS_STATE_HOME) {
21531 proc.lastCachedPss = pss;
21532 proc.lastCachedSwapPss = swapPss;
21533 }
21534
21535 final SparseArray<Pair<Long, String>> watchUids
21536 = mMemWatchProcesses.getMap().get(proc.processName);
21537 Long check = null;
21538 if (watchUids != null) {
21539 Pair<Long, String> val = watchUids.get(proc.uid);
21540 if (val == null) {
21541 val = watchUids.get(0);
21542 }
21543 if (val != null) {
21544 check = val.first;
21545 }
21546 }
21547 if (check != null) {
21548 if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
21549 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
21550 if (!isDebuggable) {
21551 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
21552 isDebuggable = true;
21553 }
21554 }
21555 if (isDebuggable) {
21556 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting");
21557 final ProcessRecord myProc = proc;
21558 final File heapdumpFile = DumpHeapProvider.getJavaFile();
21559 mMemWatchDumpProcName = proc.processName;
21560 mMemWatchDumpFile = heapdumpFile.toString();
21561 mMemWatchDumpPid = proc.pid;
21562 mMemWatchDumpUid = proc.uid;
21563 BackgroundThread.getHandler().post(new Runnable() {
21564 @Override
21565 public void run() {
21566 revokeUriPermission(ActivityThread.currentActivityThread()
21567 .getApplicationThread(),
21568 null, DumpHeapActivity.JAVA_URI,
21569 Intent.FLAG_GRANT_READ_URI_PERMISSION
21570 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
21571 UserHandle.myUserId());
21572 ParcelFileDescriptor fd = null;
21573 try {
21574 heapdumpFile.delete();
21575 fd = ParcelFileDescriptor.open(heapdumpFile,
21576 ParcelFileDescriptor.MODE_CREATE |
21577 ParcelFileDescriptor.MODE_TRUNCATE |
21578 ParcelFileDescriptor.MODE_WRITE_ONLY |
21579 ParcelFileDescriptor.MODE_APPEND);
21580 IApplicationThread thread = myProc.thread;
21581 if (thread != null) {
21582 try {
21583 if (DEBUG_PSS) Slog.d(TAG_PSS,
21584 "Requesting dump heap from "
21585 + myProc + " to " + heapdumpFile);
21586 thread.dumpHeap(true, heapdumpFile.toString(), fd);
21587 } catch (RemoteException e) {
21588 }
21589 }
21590 } catch (FileNotFoundException e) {
21591 e.printStackTrace();
21592 } finally {
21593 if (fd != null) {
21594 try {
21595 fd.close();
21596 } catch (IOException e) {
21597 }
21598 }
21599 }
21600 }
21601 });
21602 } else {
21603 Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check
21604 + ", but debugging not enabled");
21605 }
21606 }
21607 }
21608 }
21609
21610 /**
21611 * Schedule PSS collection of a process.
21612 */
21613 void requestPssLocked(ProcessRecord proc, int procState) {
21614 if (mPendingPssProcesses.contains(proc)) {
21615 return;
21616 }
21617 if (mPendingPssProcesses.size() == 0) {
21618 mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
21619 }
21620 if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of: " + proc);
21621 proc.pssProcState = procState;
21622 mPendingPssProcesses.add(proc);
21623 }
21624
21625 /**
21626 * Schedule PSS collection of all processes.
21627 */
21628 void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
21629 if (!always) {
21630 if (now < (mLastFullPssTime +
21631 (memLowered ? mConstants.FULL_PSS_LOWERED_INTERVAL
21632 : mConstants.FULL_PSS_MIN_INTERVAL))) {
21633 return;
21634 }
21635 }
21636 if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of all procs! memLowered=" + memLowered);
21637 mLastFullPssTime = now;
21638 mFullPssPending = true;
21639 mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
21640 mPendingPssProcesses.clear();
21641 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
21642 ProcessRecord app = mLruProcesses.get(i);
21643 if (app.thread == null
21644 || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
21645 continue;
21646 }
21647 if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
21648 app.pssProcState = app.setProcState;
21649 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
21650 mTestPssMode, isSleepingLocked(), now);
21651 mPendingPssProcesses.add(app);
21652 }
21653 }
21654 mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
21655 }
21656
21657 public void setTestPssMode(boolean enabled) {
21658 synchronized (this) {
21659 mTestPssMode = enabled;
21660 if (enabled) {
21661 // Whenever we enable the mode, we want to take a snapshot all of current
21662 // process mem use.
21663 requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, true);
21664 }
21665 }
21666 }
21667
21668 /**
21669 * Ask a given process to GC right now.
21670 */
21671 final void performAppGcLocked(ProcessRecord app) {
21672 try {
21673 app.lastRequestedGc = SystemClock.uptimeMillis();
21674 if (app.thread != null) {
21675 if (app.reportLowMemory) {
21676 app.reportLowMemory = false;
21677 app.thread.scheduleLowMemory();
21678 } else {
21679 app.thread.processInBackground();
21680 }
21681 }
21682 } catch (Exception e) {
21683 // whatever.
21684 }
21685 }
21686
21687 /**
21688 * Returns true if things are idle enough to perform GCs.
21689 */
21690 private final boolean canGcNowLocked() {
21691 boolean processingBroadcasts = false;
21692 for (BroadcastQueue q : mBroadcastQueues) {
21693 if (q.mParallelBroadcasts.size() != 0 || q.mOrderedBroadcasts.size() != 0) {
21694 processingBroadcasts = true;
21695 }
21696 }
21697 return !processingBroadcasts
21698 && (isSleepingLocked() || mStackSupervisor.allResumedActivitiesIdle());
21699 }
21700
21701 /**
21702 * Perform GCs on all processes that are waiting for it, but only
21703 * if things are idle.
21704 */
21705 final void performAppGcsLocked() {
21706 final int N = mProcessesToGc.size();
21707 if (N <= 0) {
21708 return;
21709 }
21710 if (canGcNowLocked()) {
21711 while (mProcessesToGc.size() > 0) {
21712 ProcessRecord proc = mProcessesToGc.remove(0);
21713 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
21714 if ((proc.lastRequestedGc+mConstants.GC_MIN_INTERVAL)
21715 <= SystemClock.uptimeMillis()) {
21716 // To avoid spamming the system, we will GC processes one
21717 // at a time, waiting a few seconds between each.
21718 performAppGcLocked(proc);
21719 scheduleAppGcsLocked();
21720 return;
21721 } else {
21722 // It hasn't been long enough since we last GCed this
21723 // process... put it in the list to wait for its time.
21724 addProcessToGcListLocked(proc);
21725 break;
21726 }
21727 }
21728 }
21729
21730 scheduleAppGcsLocked();
21731 }
21732 }
21733
21734 /**
21735 * If all looks good, perform GCs on all processes waiting for them.
21736 */
21737 final void performAppGcsIfAppropriateLocked() {
21738 if (canGcNowLocked()) {
21739 performAppGcsLocked();
21740 return;
21741 }
21742 // Still not idle, wait some more.
21743 scheduleAppGcsLocked();
21744 }
21745
21746 /**
21747 * Schedule the execution of all pending app GCs.
21748 */
21749 final void scheduleAppGcsLocked() {
21750 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
21751
21752 if (mProcessesToGc.size() > 0) {
21753 // Schedule a GC for the time to the next process.
21754 ProcessRecord proc = mProcessesToGc.get(0);
21755 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
21756
21757 long when = proc.lastRequestedGc + mConstants.GC_MIN_INTERVAL;
21758 long now = SystemClock.uptimeMillis();
21759 if (when < (now+mConstants.GC_TIMEOUT)) {
21760 when = now + mConstants.GC_TIMEOUT;
21761 }
21762 mHandler.sendMessageAtTime(msg, when);
21763 }
21764 }
21765
21766 /**
21767 * Add a process to the array of processes waiting to be GCed. Keeps the
21768 * list in sorted order by the last GC time. The process can't already be
21769 * on the list.
21770 */
21771 final void addProcessToGcListLocked(ProcessRecord proc) {
21772 boolean added = false;
21773 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
21774 if (mProcessesToGc.get(i).lastRequestedGc <
21775 proc.lastRequestedGc) {
21776 added = true;
21777 mProcessesToGc.add(i+1, proc);
21778 break;
21779 }
21780 }
21781 if (!added) {
21782 mProcessesToGc.add(0, proc);
21783 }
21784 }
21785
21786 /**
21787 * Set up to ask a process to GC itself. This will either do it
21788 * immediately, or put it on the list of processes to gc the next
21789 * time things are idle.
21790 */
21791 final void scheduleAppGcLocked(ProcessRecord app) {
21792 long now = SystemClock.uptimeMillis();
21793 if ((app.lastRequestedGc+mConstants.GC_MIN_INTERVAL) > now) {
21794 return;
21795 }
21796 if (!mProcessesToGc.contains(app)) {
21797 addProcessToGcListLocked(app);
21798 scheduleAppGcsLocked();
21799 }
21800 }
21801
21802 final void checkExcessivePowerUsageLocked(boolean doKills) {
21803 updateCpuStatsNow();
21804
21805 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
21806 boolean doWakeKills = doKills;
21807 boolean doCpuKills = doKills;
21808 if (mLastPowerCheckRealtime == 0) {
21809 doWakeKills = false;
21810 }
21811 if (mLastPowerCheckUptime == 0) {
21812 doCpuKills = false;
21813 }
21814 if (stats.isScreenOn()) {
21815 doWakeKills = false;
21816 }
21817 final long curRealtime = SystemClock.elapsedRealtime();
21818 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
21819 final long curUptime = SystemClock.uptimeMillis();
21820 final long uptimeSince = curUptime - mLastPowerCheckUptime;
21821 mLastPowerCheckRealtime = curRealtime;
21822 mLastPowerCheckUptime = curUptime;
21823 if (realtimeSince < mConstants.WAKE_LOCK_MIN_CHECK_DURATION) {
21824 doWakeKills = false;
21825 }
21826 if (uptimeSince < mConstants.CPU_MIN_CHECK_DURATION) {
21827 doCpuKills = false;
21828 }
21829 int i = mLruProcesses.size();
21830 while (i > 0) {
21831 i--;
21832 ProcessRecord app = mLruProcesses.get(i);
21833 if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
21834 long wtime;
21835 synchronized (stats) {
21836 wtime = stats.getProcessWakeTime(app.info.uid,
21837 app.pid, curRealtime);
21838 }
21839 long wtimeUsed = wtime - app.lastWakeTime;
21840 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
21841 if (DEBUG_POWER) {
21842 StringBuilder sb = new StringBuilder(128);
21843 sb.append("Wake for ");
21844 app.toShortString(sb);
21845 sb.append(": over ");
21846 TimeUtils.formatDuration(realtimeSince, sb);
21847 sb.append(" used ");
21848 TimeUtils.formatDuration(wtimeUsed, sb);
21849 sb.append(" (");
21850 sb.append((wtimeUsed*100)/realtimeSince);
21851 sb.append("%)");
21852 Slog.i(TAG_POWER, sb.toString());
21853 sb.setLength(0);
21854 sb.append("CPU for ");
21855 app.toShortString(sb);
21856 sb.append(": over ");
21857 TimeUtils.formatDuration(uptimeSince, sb);
21858 sb.append(" used ");
21859 TimeUtils.formatDuration(cputimeUsed, sb);
21860 sb.append(" (");
21861 sb.append((cputimeUsed*100)/uptimeSince);
21862 sb.append("%)");
21863 Slog.i(TAG_POWER, sb.toString());
21864 }
21865 // If a process has held a wake lock for more
21866 // than 50% of the time during this period,
21867 // that sounds bad. Kill!
21868 if (doWakeKills && realtimeSince > 0
21869 && ((wtimeUsed*100)/realtimeSince) >= 50) {
21870 synchronized (stats) {
21871 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
21872 realtimeSince, wtimeUsed);
21873 }
21874 app.kill("excessive wake held " + wtimeUsed + " during " + realtimeSince, true);
21875 app.baseProcessTracker.reportExcessiveWake(app.pkgList);
21876 } else if (doCpuKills && uptimeSince > 0
21877 && ((cputimeUsed*100)/uptimeSince) >= 25) {
21878 synchronized (stats) {
21879 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
21880 uptimeSince, cputimeUsed);
21881 }
21882 app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince, true);
21883 app.baseProcessTracker.reportExcessiveCpu(app.pkgList);
21884 } else {
21885 app.lastWakeTime = wtime;
21886 app.lastCpuTime = app.curCpuTime;
21887 }
21888 }
21889 }
21890 }
21891
21892 private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
21893 long nowElapsed) {
21894 boolean success = true;
21895
21896 if (app.curRawAdj != app.setRawAdj) {
21897 app.setRawAdj = app.curRawAdj;
21898 }
21899
21900 int changes = 0;
21901
21902 if (app.curAdj != app.setAdj) {
21903 ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
21904 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
21905 "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
21906 + app.adjType);
21907 app.setAdj = app.curAdj;
21908 app.verifiedAdj = ProcessList.INVALID_ADJ;
21909 }
21910
21911 if (app.setSchedGroup != app.curSchedGroup) {
21912 int oldSchedGroup = app.setSchedGroup;
21913 app.setSchedGroup = app.curSchedGroup;
21914 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
21915 "Setting sched group of " + app.processName
21916 + " to " + app.curSchedGroup);
21917 if (app.waitingToKill != null && app.curReceivers.isEmpty()
21918 && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
21919 app.kill(app.waitingToKill, true);
21920 success = false;
21921 } else {
21922 int processGroup;
21923 switch (app.curSchedGroup) {
21924 case ProcessList.SCHED_GROUP_BACKGROUND:
21925 processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
21926 break;
21927 case ProcessList.SCHED_GROUP_TOP_APP:
21928 case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
21929 processGroup = THREAD_GROUP_TOP_APP;
21930 break;
21931 default:
21932 processGroup = THREAD_GROUP_DEFAULT;
21933 break;
21934 }
21935 long oldId = Binder.clearCallingIdentity();
21936 try {
21937 setProcessGroup(app.pid, processGroup);
21938 if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
21939 // do nothing if we already switched to RT
21940 if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
21941 mVrController.onTopProcChangedLocked(app);
21942 if (mUseFifoUiScheduling) {
21943 // Switch UI pipeline for app to SCHED_FIFO
21944 app.savedPriority = Process.getThreadPriority(app.pid);
21945 scheduleAsFifoPriority(app.pid, /* suppressLogs */true);
21946 if (app.renderThreadTid != 0) {
21947 scheduleAsFifoPriority(app.renderThreadTid,
21948 /* suppressLogs */true);
21949 if (DEBUG_OOM_ADJ) {
21950 Slog.d("UI_FIFO", "Set RenderThread (TID " +
21951 app.renderThreadTid + ") to FIFO");
21952 }
21953 } else {
21954 if (DEBUG_OOM_ADJ) {
21955 Slog.d("UI_FIFO", "Not setting RenderThread TID");
21956 }
21957 }
21958 } else {
21959 // Boost priority for top app UI and render threads
21960 setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
21961 if (app.renderThreadTid != 0) {
21962 try {
21963 setThreadPriority(app.renderThreadTid,
21964 TOP_APP_PRIORITY_BOOST);
21965 } catch (IllegalArgumentException e) {
21966 // thread died, ignore
21967 }
21968 }
21969 }
21970 }
21971 } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
21972 app.curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
21973 mVrController.onTopProcChangedLocked(app);
21974 if (mUseFifoUiScheduling) {
21975 // Reset UI pipeline to SCHED_OTHER
21976 setThreadScheduler(app.pid, SCHED_OTHER, 0);
21977 setThreadPriority(app.pid, app.savedPriority);
21978 if (app.renderThreadTid != 0) {
21979 setThreadScheduler(app.renderThreadTid,
21980 SCHED_OTHER, 0);
21981 setThreadPriority(app.renderThreadTid, -4);
21982 }
21983 } else {
21984 // Reset priority for top app UI and render threads
21985 setThreadPriority(app.pid, 0);
21986 if (app.renderThreadTid != 0) {
21987 setThreadPriority(app.renderThreadTid, 0);
21988 }
21989 }
21990 }
21991 } catch (Exception e) {
21992 if (false) {
21993 Slog.w(TAG, "Failed setting process group of " + app.pid
21994 + " to " + app.curSchedGroup);
21995 Slog.w(TAG, "at location", e);
21996 }
21997 } finally {
21998 Binder.restoreCallingIdentity(oldId);
21999 }
22000 }
22001 }
22002 if (app.repForegroundActivities != app.foregroundActivities) {
22003 app.repForegroundActivities = app.foregroundActivities;
22004 changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
22005 }
22006 if (app.repProcState != app.curProcState) {
22007 app.repProcState = app.curProcState;
22008 if (app.thread != null) {
22009 try {
22010 if (false) {
22011 //RuntimeException h = new RuntimeException("here");
22012 Slog.i(TAG, "Sending new process state " + app.repProcState
22013 + " to " + app /*, h*/);
22014 }
22015 app.thread.setProcessState(app.repProcState);
22016 } catch (RemoteException e) {
22017 }
22018 }
22019 }
22020 if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
22021 || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
22022 if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
22023 // Experimental code to more aggressively collect pss while
22024 // running test... the problem is that this tends to collect
22025 // the data right when a process is transitioning between process
22026 // states, which well tend to give noisy data.
22027 long start = SystemClock.uptimeMillis();
22028 long pss = Debug.getPss(app.pid, mTmpLong, null);
22029 recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1], now);
22030 mPendingPssProcesses.remove(app);
22031 Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
22032 + " to " + app.curProcState + ": "
22033 + (SystemClock.uptimeMillis()-start) + "ms");
22034 }
22035 app.lastStateTime = now;
22036 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
22037 mTestPssMode, isSleepingLocked(), now);
22038 if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
22039 + ProcessList.makeProcStateString(app.setProcState) + " to "
22040 + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
22041 + (app.nextPssTime-now) + ": " + app);
22042 } else {
22043 if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
22044 && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
22045 mTestPssMode)))) {
22046 requestPssLocked(app, app.setProcState);
22047 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
22048 mTestPssMode, isSleepingLocked(), now);
22049 } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
22050 "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
22051 }
22052 if (app.setProcState != app.curProcState) {
22053 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22054 "Proc state change of " + app.processName
22055 + " to " + app.curProcState);
22056 boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
22057 boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
22058 if (setImportant && !curImportant) {
22059 // This app is no longer something we consider important enough to allow to
22060 // use arbitrary amounts of battery power. Note
22061 // its current wake lock time to later know to kill it if
22062 // it is not behaving well.
22063 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
22064 synchronized (stats) {
22065 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
22066 app.pid, nowElapsed);
22067 }
22068 app.lastCpuTime = app.curCpuTime;
22069
22070 }
22071 // Inform UsageStats of important process state change
22072 // Must be called before updating setProcState
22073 maybeUpdateUsageStatsLocked(app, nowElapsed);
22074
22075 app.setProcState = app.curProcState;
22076 if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
22077 app.notCachedSinceIdle = false;
22078 }
22079 if (!doingAll) {
22080 setProcessTrackerStateLocked(app, mProcessStats.getMemFactorLocked(), now);
22081 } else {
22082 app.procStateChanged = true;
22083 }
22084 } else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime)
22085 > mConstants.USAGE_STATS_INTERACTION_INTERVAL) {
22086 // For apps that sit around for a long time in the interactive state, we need
22087 // to report this at least once a day so they don't go idle.
22088 maybeUpdateUsageStatsLocked(app, nowElapsed);
22089 }
22090
22091 if (changes != 0) {
22092 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22093 "Changes in " + app + ": " + changes);
22094 int i = mPendingProcessChanges.size()-1;
22095 ProcessChangeItem item = null;
22096 while (i >= 0) {
22097 item = mPendingProcessChanges.get(i);
22098 if (item.pid == app.pid) {
22099 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22100 "Re-using existing item: " + item);
22101 break;
22102 }
22103 i--;
22104 }
22105 if (i < 0) {
22106 // No existing item in pending changes; need a new one.
22107 final int NA = mAvailProcessChanges.size();
22108 if (NA > 0) {
22109 item = mAvailProcessChanges.remove(NA-1);
22110 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22111 "Retrieving available item: " + item);
22112 } else {
22113 item = new ProcessChangeItem();
22114 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22115 "Allocating new item: " + item);
22116 }
22117 item.changes = 0;
22118 item.pid = app.pid;
22119 item.uid = app.info.uid;
22120 if (mPendingProcessChanges.size() == 0) {
22121 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22122 "*** Enqueueing dispatch processes changed!");
22123 mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG).sendToTarget();
22124 }
22125 mPendingProcessChanges.add(item);
22126 }
22127 item.changes |= changes;
22128 item.foregroundActivities = app.repForegroundActivities;
22129 if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
22130 "Item " + Integer.toHexString(System.identityHashCode(item))
22131 + " " + app.toShortString() + ": changes=" + item.changes
22132 + " foreground=" + item.foregroundActivities
22133 + " type=" + app.adjType + " source=" + app.adjSource
22134 + " target=" + app.adjTarget);
22135 }
22136
22137 return success;
22138 }
22139
22140 private boolean isEphemeralLocked(int uid) {
22141 String packages[] = mContext.getPackageManager().getPackagesForUid(uid);
22142 if (packages == null || packages.length != 1) { // Ephemeral apps cannot share uid
22143 return false;
22144 }
22145 return getPackageManagerInternalLocked().isPackageEphemeral(UserHandle.getUserId(uid),
22146 packages[0]);
22147 }
22148
22149 @VisibleForTesting
22150 final void enqueueUidChangeLocked(UidRecord uidRec, int uid, int change) {
22151 final UidRecord.ChangeItem pendingChange;
22152 if (uidRec == null || uidRec.pendingChange == null) {
22153 if (mPendingUidChanges.size() == 0) {
22154 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
22155 "*** Enqueueing dispatch uid changed!");
22156 mUiHandler.obtainMessage(DISPATCH_UIDS_CHANGED_UI_MSG).sendToTarget();
22157 }
22158 final int NA = mAvailUidChanges.size();
22159 if (NA > 0) {
22160 pendingChange = mAvailUidChanges.remove(NA-1);
22161 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
22162 "Retrieving available item: " + pendingChange);
22163 } else {
22164 pendingChange = new UidRecord.ChangeItem();
22165 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
22166 "Allocating new item: " + pendingChange);
22167 }
22168 if (uidRec != null) {
22169 uidRec.pendingChange = pendingChange;
22170 if (change == UidRecord.CHANGE_GONE && !uidRec.idle) {
22171 // If this uid is going away, and we haven't yet reported it is gone,
22172 // then do so now.
22173 change = UidRecord.CHANGE_GONE_IDLE;
22174 }
22175 } else if (uid < 0) {
22176 throw new IllegalArgumentException("No UidRecord or uid");
22177 }
22178 pendingChange.uidRecord = uidRec;
22179 pendingChange.uid = uidRec != null ? uidRec.uid : uid;
22180 mPendingUidChanges.add(pendingChange);
22181 } else {
22182 pendingChange = uidRec.pendingChange;
22183 if (change == UidRecord.CHANGE_GONE && pendingChange.change == UidRecord.CHANGE_IDLE) {
22184 change = UidRecord.CHANGE_GONE_IDLE;
22185 }
22186 }
22187 pendingChange.change = change;
22188 pendingChange.processState = uidRec != null
22189 ? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
22190 pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid);
22191 pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
22192 if (uidRec != null) {
22193 uidRec.updateLastDispatchedProcStateSeq(change);
22194 }
22195
22196 // Directly update the power manager, since we sit on top of it and it is critical
22197 // it be kept in sync (so wake locks will be held as soon as appropriate).
22198 if (mLocalPowerManager != null) {
22199 switch (change) {
22200 case UidRecord.CHANGE_GONE:
22201 case UidRecord.CHANGE_GONE_IDLE:
22202 mLocalPowerManager.uidGone(pendingChange.uid);
22203 break;
22204 case UidRecord.CHANGE_IDLE:
22205 mLocalPowerManager.uidIdle(pendingChange.uid);
22206 break;
22207 case UidRecord.CHANGE_ACTIVE:
22208 mLocalPowerManager.uidActive(pendingChange.uid);
22209 break;
22210 default:
22211 mLocalPowerManager.updateUidProcState(pendingChange.uid,
22212 pendingChange.processState);
22213 break;
22214 }
22215 }
22216 }
22217
22218 private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
22219 String authority) {
22220 if (app == null) return;
22221 if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
22222 UserState userState = mUserController.getStartedUserStateLocked(app.userId);
22223 if (userState == null) return;
22224 final long now = SystemClock.elapsedRealtime();
22225 Long lastReported = userState.mProviderLastReportedFg.get(authority);
22226 if (lastReported == null || lastReported < now - 60 * 1000L) {
22227 if (mSystemReady) {
22228 // Cannot touch the user stats if not system ready
22229 mUsageStatsService.reportContentProviderUsage(
22230 authority, providerPkgName, app.userId);
22231 }
22232 userState.mProviderLastReportedFg.put(authority, now);
22233 }
22234 }
22235 }
22236
22237 private void maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed) {
22238 if (DEBUG_USAGE_STATS) {
22239 Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
22240 + "] state changes: old = " + app.setProcState + ", new = "
22241 + app.curProcState);
22242 }
22243 if (mUsageStatsService == null) {
22244 return;
22245 }
22246 boolean isInteraction;
22247 // To avoid some abuse patterns, we are going to be careful about what we consider
22248 // to be an app interaction. Being the top activity doesn't count while the display
22249 // is sleeping, nor do short foreground services.
22250 if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
22251 isInteraction = true;
22252 app.fgInteractionTime = 0;
22253 } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
22254 if (app.fgInteractionTime == 0) {
22255 app.fgInteractionTime = nowElapsed;
22256 isInteraction = false;
22257 } else {
22258 isInteraction = nowElapsed > app.fgInteractionTime
22259 + mConstants.SERVICE_USAGE_INTERACTION_TIME;
22260 }
22261 } else {
22262 isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
22263 app.fgInteractionTime = 0;
22264 }
22265 if (isInteraction && (!app.reportedInteraction || (nowElapsed-app.interactionEventTime)
22266 > mConstants.USAGE_STATS_INTERACTION_INTERVAL)) {
22267 app.interactionEventTime = nowElapsed;
22268 String[] packages = app.getPackageList();
22269 if (packages != null) {
22270 for (int i = 0; i < packages.length; i++) {
22271 mUsageStatsService.reportEvent(packages[i], app.userId,
22272 UsageEvents.Event.SYSTEM_INTERACTION);
22273 }
22274 }
22275 }
22276 app.reportedInteraction = isInteraction;
22277 if (!isInteraction) {
22278 app.interactionEventTime = 0;
22279 }
22280 }
22281
22282 private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
22283 if (proc.thread != null) {
22284 if (proc.baseProcessTracker != null) {
22285 proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
22286 }
22287 }
22288 }
22289
22290 private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
22291 ProcessRecord TOP_APP, boolean doingAll, long now) {
22292 if (app.thread == null) {
22293 return false;
22294 }
22295
22296 computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
22297
22298 return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
22299 }
22300
22301 final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
22302 boolean oomAdj) {
22303 if (isForeground != proc.foregroundServices) {
22304 proc.foregroundServices = isForeground;
22305 ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName,
22306 proc.info.uid);
22307 if (isForeground) {
22308 if (curProcs == null) {
22309 curProcs = new ArrayList<ProcessRecord>();
22310 mForegroundPackages.put(proc.info.packageName, proc.info.uid, curProcs);
22311 }
22312 if (!curProcs.contains(proc)) {
22313 curProcs.add(proc);
22314 mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_FOREGROUND_START,
22315 proc.info.packageName, proc.info.uid);
22316 }
22317 } else {
22318 if (curProcs != null) {
22319 if (curProcs.remove(proc)) {
22320 mBatteryStatsService.noteEvent(
22321 BatteryStats.HistoryItem.EVENT_FOREGROUND_FINISH,
22322 proc.info.packageName, proc.info.uid);
22323 if (curProcs.size() <= 0) {
22324 mForegroundPackages.remove(proc.info.packageName, proc.info.uid);
22325 }
22326 }
22327 }
22328 }
22329 if (oomAdj) {
22330 updateOomAdjLocked();
22331 }
22332 }
22333 }
22334
22335 private final ActivityRecord resumedAppLocked() {
22336 ActivityRecord act = mStackSupervisor.getResumedActivityLocked();
22337 String pkg;
22338 int uid;
22339 if (act != null) {
22340 pkg = act.packageName;
22341 uid = act.info.applicationInfo.uid;
22342 } else {
22343 pkg = null;
22344 uid = -1;
22345 }
22346 // Has the UID or resumed package name changed?
22347 if (uid != mCurResumedUid || (pkg != mCurResumedPackage
22348 && (pkg == null || !pkg.equals(mCurResumedPackage)))) {
22349 if (mCurResumedPackage != null) {
22350 mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_FINISH,
22351 mCurResumedPackage, mCurResumedUid);
22352 }
22353 mCurResumedPackage = pkg;
22354 mCurResumedUid = uid;
22355 if (mCurResumedPackage != null) {
22356 mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_START,
22357 mCurResumedPackage, mCurResumedUid);
22358 }
22359 }
22360 return act;
22361 }
22362
22363 /**
22364 * Update OomAdj for a specific process.
22365 * @param app The process to update
22366 * @param oomAdjAll If it's ok to call updateOomAdjLocked() for all running apps
22367 * if necessary, or skip.
22368 * @return whether updateOomAdjLocked(app) was successful.
22369 */
22370 final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll) {
22371 final ActivityRecord TOP_ACT = resumedAppLocked();
22372 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
22373 final boolean wasCached = app.cached;
22374
22375 mAdjSeq++;
22376
22377 // This is the desired cached adjusment we want to tell it to use.
22378 // If our app is currently cached, we know it, and that is it. Otherwise,
22379 // we don't know it yet, and it needs to now be cached we will then
22380 // need to do a complete oom adj.
22381 final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
22382 ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;
22383 boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
22384 SystemClock.uptimeMillis());
22385 if (oomAdjAll
22386 && (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ)) {
22387 // Changed to/from cached state, so apps after it in the LRU
22388 // list may also be changed.
22389 updateOomAdjLocked();
22390 }
22391 return success;
22392 }
22393
22394 final void updateOomAdjLocked() {
22395 final ActivityRecord TOP_ACT = resumedAppLocked();
22396 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
22397 final long now = SystemClock.uptimeMillis();
22398 final long nowElapsed = SystemClock.elapsedRealtime();
22399 final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
22400 final int N = mLruProcesses.size();
22401
22402 if (false) {
22403 RuntimeException e = new RuntimeException();
22404 e.fillInStackTrace();
22405 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
22406 }
22407
22408 // Reset state in all uid records.
22409 for (int i=mActiveUids.size()-1; i>=0; i--) {
22410 final UidRecord uidRec = mActiveUids.valueAt(i);
22411 if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
22412 "Starting update of " + uidRec);
22413 uidRec.reset();
22414 }
22415
22416 mStackSupervisor.rankTaskLayersIfNeeded();
22417
22418 mAdjSeq++;
22419 mNewNumServiceProcs = 0;
22420 mNewNumAServiceProcs = 0;
22421
22422 final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
22423 final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit;
22424
22425 // Let's determine how many processes we have running vs.
22426 // how many slots we have for background processes; we may want
22427 // to put multiple processes in a slot of there are enough of
22428 // them.
22429 int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
22430 - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
22431 int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
22432 if (numEmptyProcs > cachedProcessLimit) {
22433 // If there are more empty processes than our limit on cached
22434 // processes, then use the cached process limit for the factor.
22435 // This ensures that the really old empty processes get pushed
22436 // down to the bottom, so if we are running low on memory we will
22437 // have a better chance at keeping around more cached processes
22438 // instead of a gazillion empty processes.
22439 numEmptyProcs = cachedProcessLimit;
22440 }
22441 int emptyFactor = numEmptyProcs/numSlots;
22442 if (emptyFactor < 1) emptyFactor = 1;
22443 int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
22444 if (cachedFactor < 1) cachedFactor = 1;
22445 int stepCached = 0;
22446 int stepEmpty = 0;
22447 int numCached = 0;
22448 int numEmpty = 0;
22449 int numTrimming = 0;
22450
22451 mNumNonCachedProcs = 0;
22452 mNumCachedHiddenProcs = 0;
22453
22454 // First update the OOM adjustment for each of the
22455 // application processes based on their current state.
22456 int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
22457 int nextCachedAdj = curCachedAdj+1;
22458 int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
22459 int nextEmptyAdj = curEmptyAdj+2;
22460 for (int i=N-1; i>=0; i--) {
22461 ProcessRecord app = mLruProcesses.get(i);
22462 if (!app.killedByAm && app.thread != null) {
22463 app.procStateChanged = false;
22464 computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
22465
22466 // If we haven't yet assigned the final cached adj
22467 // to the process, do that now.
22468 if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
22469 switch (app.curProcState) {
22470 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
22471 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
22472 // This process is a cached process holding activities...
22473 // assign it the next cached value for that type, and then
22474 // step that cached level.
22475 app.curRawAdj = curCachedAdj;
22476 app.curAdj = app.modifyRawOomAdj(curCachedAdj);
22477 if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
22478 + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
22479 + ")");
22480 if (curCachedAdj != nextCachedAdj) {
22481 stepCached++;
22482 if (stepCached >= cachedFactor) {
22483 stepCached = 0;
22484 curCachedAdj = nextCachedAdj;
22485 nextCachedAdj += 2;
22486 if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
22487 nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
22488 }
22489 }
22490 }
22491 break;
22492 default:
22493 // For everything else, assign next empty cached process
22494 // level and bump that up. Note that this means that
22495 // long-running services that have dropped down to the
22496 // cached level will be treated as empty (since their process
22497 // state is still as a service), which is what we want.
22498 app.curRawAdj = curEmptyAdj;
22499 app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
22500 if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
22501 + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
22502 + ")");
22503 if (curEmptyAdj != nextEmptyAdj) {
22504 stepEmpty++;
22505 if (stepEmpty >= emptyFactor) {
22506 stepEmpty = 0;
22507 curEmptyAdj = nextEmptyAdj;
22508 nextEmptyAdj += 2;
22509 if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
22510 nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
22511 }
22512 }
22513 }
22514 break;
22515 }
22516 }
22517
22518 applyOomAdjLocked(app, true, now, nowElapsed);
22519
22520 // Count the number of process types.
22521 switch (app.curProcState) {
22522 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
22523 case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
22524 mNumCachedHiddenProcs++;
22525 numCached++;
22526 if (numCached > cachedProcessLimit) {
22527 app.kill("cached #" + numCached, true);
22528 }
22529 break;
22530 case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
22531 if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
22532 && app.lastActivityTime < oldTime) {
22533 app.kill("empty for "
22534 + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
22535 / 1000) + "s", true);
22536 } else {
22537 numEmpty++;
22538 if (numEmpty > emptyProcessLimit) {
22539 app.kill("empty #" + numEmpty, true);
22540 }
22541 }
22542 break;
22543 default:
22544 mNumNonCachedProcs++;
22545 break;
22546 }
22547
22548 if (app.isolated && app.services.size() <= 0) {
22549 // If this is an isolated process, and there are no
22550 // services running in it, then the process is no longer
22551 // needed. We agressively kill these because we can by
22552 // definition not re-use the same process again, and it is
22553 // good to avoid having whatever code was running in them
22554 // left sitting around after no longer needed.
22555 app.kill("isolated not needed", true);
22556 } else {
22557 // Keeping this process, update its uid.
22558 final UidRecord uidRec = app.uidRecord;
22559 if (uidRec != null) {
22560 uidRec.ephemeral = app.info.isInstantApp();
22561 if (uidRec.curProcState > app.curProcState) {
22562 uidRec.curProcState = app.curProcState;
22563 }
22564 if (app.foregroundServices) {
22565 uidRec.foregroundServices = true;
22566 }
22567 }
22568 }
22569
22570 if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
22571 && !app.killedByAm) {
22572 numTrimming++;
22573 }
22574 }
22575 }
22576
22577 incrementProcStateSeqAndNotifyAppsLocked();
22578
22579 mNumServiceProcs = mNewNumServiceProcs;
22580
22581 // Now determine the memory trimming level of background processes.
22582 // Unfortunately we need to start at the back of the list to do this
22583 // properly. We only do this if the number of background apps we
22584 // are managing to keep around is less than half the maximum we desire;
22585 // if we are keeping a good number around, we'll let them use whatever
22586 // memory they want.
22587 final int numCachedAndEmpty = numCached + numEmpty;
22588 int memFactor;
22589 if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
22590 && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
22591 if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
22592 memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
22593 } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
22594 memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
22595 } else {
22596 memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
22597 }
22598 } else {
22599 memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
22600 }
22601 // We always allow the memory level to go up (better). We only allow it to go
22602 // down if we are in a state where that is allowed, *and* the total number of processes
22603 // has gone down since last time.
22604 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
22605 + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
22606 + " numProcs=" + mLruProcesses.size() + " last=" + mLastNumProcesses);
22607 if (memFactor > mLastMemoryLevel) {
22608 if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
22609 memFactor = mLastMemoryLevel;
22610 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
22611 }
22612 }
22613 if (memFactor != mLastMemoryLevel) {
22614 EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
22615 }
22616 mLastMemoryLevel = memFactor;
22617 mLastNumProcesses = mLruProcesses.size();
22618 boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
22619 final int trackerMemFactor = mProcessStats.getMemFactorLocked();
22620 if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
22621 if (mLowRamStartTime == 0) {
22622 mLowRamStartTime = now;
22623 }
22624 int step = 0;
22625 int fgTrimLevel;
22626 switch (memFactor) {
22627 case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
22628 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
22629 break;
22630 case ProcessStats.ADJ_MEM_FACTOR_LOW:
22631 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
22632 break;
22633 default:
22634 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
22635 break;
22636 }
22637 int factor = numTrimming/3;
22638 int minFactor = 2;
22639 if (mHomeProcess != null) minFactor++;
22640 if (mPreviousProcess != null) minFactor++;
22641 if (factor < minFactor) factor = minFactor;
22642 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
22643 for (int i=N-1; i>=0; i--) {
22644 ProcessRecord app = mLruProcesses.get(i);
22645 if (allChanged || app.procStateChanged) {
22646 setProcessTrackerStateLocked(app, trackerMemFactor, now);
22647 app.procStateChanged = false;
22648 }
22649 if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
22650 && !app.killedByAm) {
22651 if (app.trimMemoryLevel < curLevel && app.thread != null) {
22652 try {
22653 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22654 "Trimming memory of " + app.processName + " to " + curLevel);
22655 app.thread.scheduleTrimMemory(curLevel);
22656 } catch (RemoteException e) {
22657 }
22658 if (false) {
22659 // For now we won't do this; our memory trimming seems
22660 // to be good enough at this point that destroying
22661 // activities causes more harm than good.
22662 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
22663 && app != mHomeProcess && app != mPreviousProcess) {
22664 // Need to do this on its own message because the stack may not
22665 // be in a consistent state at this point.
22666 // For these apps we will also finish their activities
22667 // to help them free memory.
22668 mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
22669 }
22670 }
22671 }
22672 app.trimMemoryLevel = curLevel;
22673 step++;
22674 if (step >= factor) {
22675 step = 0;
22676 switch (curLevel) {
22677 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
22678 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
22679 break;
22680 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
22681 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
22682 break;
22683 }
22684 }
22685 } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
22686 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
22687 && app.thread != null) {
22688 try {
22689 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22690 "Trimming memory of heavy-weight " + app.processName
22691 + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
22692 app.thread.scheduleTrimMemory(
22693 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
22694 } catch (RemoteException e) {
22695 }
22696 }
22697 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
22698 } else {
22699 if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
22700 || app.systemNoUi) && app.pendingUiClean) {
22701 // If this application is now in the background and it
22702 // had done UI, then give it the special trim level to
22703 // have it free UI resources.
22704 final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
22705 if (app.trimMemoryLevel < level && app.thread != null) {
22706 try {
22707 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22708 "Trimming memory of bg-ui " + app.processName
22709 + " to " + level);
22710 app.thread.scheduleTrimMemory(level);
22711 } catch (RemoteException e) {
22712 }
22713 }
22714 app.pendingUiClean = false;
22715 }
22716 if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
22717 try {
22718 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22719 "Trimming memory of fg " + app.processName
22720 + " to " + fgTrimLevel);
22721 app.thread.scheduleTrimMemory(fgTrimLevel);
22722 } catch (RemoteException e) {
22723 }
22724 }
22725 app.trimMemoryLevel = fgTrimLevel;
22726 }
22727 }
22728 } else {
22729 if (mLowRamStartTime != 0) {
22730 mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
22731 mLowRamStartTime = 0;
22732 }
22733 for (int i=N-1; i>=0; i--) {
22734 ProcessRecord app = mLruProcesses.get(i);
22735 if (allChanged || app.procStateChanged) {
22736 setProcessTrackerStateLocked(app, trackerMemFactor, now);
22737 app.procStateChanged = false;
22738 }
22739 if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
22740 || app.systemNoUi) && app.pendingUiClean) {
22741 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
22742 && app.thread != null) {
22743 try {
22744 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
22745 "Trimming memory of ui hidden " + app.processName
22746 + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
22747 app.thread.scheduleTrimMemory(
22748 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
22749 } catch (RemoteException e) {
22750 }
22751 }
22752 app.pendingUiClean = false;
22753 }
22754 app.trimMemoryLevel = 0;
22755 }
22756 }
22757
22758 if (mAlwaysFinishActivities) {
22759 // Need to do this on its own message because the stack may not
22760 // be in a consistent state at this point.
22761 mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
22762 }
22763
22764 if (allChanged) {
22765 requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
22766 }
22767
22768 // Update from any uid changes.
22769 if (mLocalPowerManager != null) {
22770 mLocalPowerManager.startUidChanges();
22771 }
22772 for (int i=mActiveUids.size()-1; i>=0; i--) {
22773 final UidRecord uidRec = mActiveUids.valueAt(i);
22774 int uidChange = UidRecord.CHANGE_PROCSTATE;
22775 if (uidRec.setProcState != uidRec.curProcState
22776 || uidRec.setWhitelist != uidRec.curWhitelist) {
22777 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
22778 "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
22779 + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
22780 + " to " + uidRec.curWhitelist);
22781 if (ActivityManager.isProcStateBackground(uidRec.curProcState)
22782 && !uidRec.curWhitelist) {
22783 // UID is now in the background (and not on the temp whitelist). Was it
22784 // previously in the foreground (or on the temp whitelist)?
22785 if (!ActivityManager.isProcStateBackground(uidRec.setProcState)
22786 || uidRec.setWhitelist) {
22787 uidRec.lastBackgroundTime = nowElapsed;
22788 if (!mHandler.hasMessages(IDLE_UIDS_MSG)) {
22789 // Note: the background settle time is in elapsed realtime, while
22790 // the handler time base is uptime. All this means is that we may
22791 // stop background uids later than we had intended, but that only
22792 // happens because the device was sleeping so we are okay anyway.
22793 mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
22794 mConstants.BACKGROUND_SETTLE_TIME);
22795 }
22796 }
22797 } else {
22798 if (uidRec.idle) {
22799 uidChange = UidRecord.CHANGE_ACTIVE;
22800 EventLogTags.writeAmUidActive(uidRec.uid);
22801 uidRec.idle = false;
22802 }
22803 uidRec.lastBackgroundTime = 0;
22804 }
22805 uidRec.setProcState = uidRec.curProcState;
22806 uidRec.setWhitelist = uidRec.curWhitelist;
22807 enqueueUidChangeLocked(uidRec, -1, uidChange);
22808 noteUidProcessState(uidRec.uid, uidRec.curProcState);
22809 if (uidRec.foregroundServices) {
22810 mServices.foregroundServiceProcStateChangedLocked(uidRec);
22811 }
22812 }
22813 }
22814 if (mLocalPowerManager != null) {
22815 mLocalPowerManager.finishUidChanges();
22816 }
22817
22818 if (mProcessStats.shouldWriteNowLocked(now)) {
22819 mHandler.post(new Runnable() {
22820 @Override public void run() {
22821 synchronized (ActivityManagerService.this) {
22822 mProcessStats.writeStateAsyncLocked();
22823 }
22824 }
22825 });
22826 }
22827
22828 if (DEBUG_OOM_ADJ) {
22829 final long duration = SystemClock.uptimeMillis() - now;
22830 if (false) {
22831 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
22832 new RuntimeException("here").fillInStackTrace());
22833 } else {
22834 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
22835 }
22836 }
22837 }
22838
22839 @Override
22840 public void makePackageIdle(String packageName, int userId) {
22841 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
22842 != PackageManager.PERMISSION_GRANTED) {
22843 String msg = "Permission Denial: makePackageIdle() from pid="
22844 + Binder.getCallingPid()
22845 + ", uid=" + Binder.getCallingUid()
22846 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
22847 Slog.w(TAG, msg);
22848 throw new SecurityException(msg);
22849 }
22850 final int callingPid = Binder.getCallingPid();
22851 userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
22852 userId, true, ALLOW_FULL_ONLY, "makePackageIdle", null);
22853 long callingId = Binder.clearCallingIdentity();
22854 synchronized(this) {
22855 try {
22856 IPackageManager pm = AppGlobals.getPackageManager();
22857 int pkgUid = -1;
22858 try {
22859 pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES
22860 | MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM);
22861 } catch (RemoteException e) {
22862 }
22863 if (pkgUid == -1) {
22864 throw new IllegalArgumentException("Unknown package name " + packageName);
22865 }
22866
22867 if (mLocalPowerManager != null) {
22868 mLocalPowerManager.startUidChanges();
22869 }
22870 final int appId = UserHandle.getAppId(pkgUid);
22871 final int N = mActiveUids.size();
22872 for (int i=N-1; i>=0; i--) {
22873 final UidRecord uidRec = mActiveUids.valueAt(i);
22874 final long bgTime = uidRec.lastBackgroundTime;
22875 if (bgTime > 0 && !uidRec.idle) {
22876 if (UserHandle.getAppId(uidRec.uid) == appId) {
22877 if (userId == UserHandle.USER_ALL ||
22878 userId == UserHandle.getUserId(uidRec.uid)) {
22879 EventLogTags.writeAmUidIdle(uidRec.uid);
22880 uidRec.idle = true;
22881 Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uidRec.uid)
22882 + " from package " + packageName + " user " + userId);
22883 doStopUidLocked(uidRec.uid, uidRec);
22884 }
22885 }
22886 }
22887 }
22888 } finally {
22889 if (mLocalPowerManager != null) {
22890 mLocalPowerManager.finishUidChanges();
22891 }
22892 Binder.restoreCallingIdentity(callingId);
22893 }
22894 }
22895 }
22896
22897 final void idleUids() {
22898 synchronized (this) {
22899 final int N = mActiveUids.size();
22900 if (N <= 0) {
22901 return;
22902 }
22903 final long nowElapsed = SystemClock.elapsedRealtime();
22904 final long maxBgTime = nowElapsed - mConstants.BACKGROUND_SETTLE_TIME;
22905 long nextTime = 0;
22906 if (mLocalPowerManager != null) {
22907 mLocalPowerManager.startUidChanges();
22908 }
22909 for (int i=N-1; i>=0; i--) {
22910 final UidRecord uidRec = mActiveUids.valueAt(i);
22911 final long bgTime = uidRec.lastBackgroundTime;
22912 if (bgTime > 0 && !uidRec.idle) {
22913 if (bgTime <= maxBgTime) {
22914 EventLogTags.writeAmUidIdle(uidRec.uid);
22915 uidRec.idle = true;
22916 doStopUidLocked(uidRec.uid, uidRec);
22917 } else {
22918 if (nextTime == 0 || nextTime > bgTime) {
22919 nextTime = bgTime;
22920 }
22921 }
22922 }
22923 }
22924 if (mLocalPowerManager != null) {
22925 mLocalPowerManager.finishUidChanges();
22926 }
22927 if (nextTime > 0) {
22928 mHandler.removeMessages(IDLE_UIDS_MSG);
22929 mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
22930 nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed);
22931 }
22932 }
22933 }
22934
22935 /**
22936 * Checks if any uid is coming from background to foreground or vice versa and if so, increments
22937 * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
22938 * {@link #mProcStateSeqCounter} and notifies the app if it needs to block.
22939 */
22940 @VisibleForTesting
22941 @GuardedBy("this")
22942 void incrementProcStateSeqAndNotifyAppsLocked() {
22943 if (mWaitForNetworkTimeoutMs <= 0) {
22944 return;
22945 }
22946 // Used for identifying which uids need to block for network.
22947 ArrayList<Integer> blockingUids = null;
22948 for (int i = mActiveUids.size() - 1; i >= 0; --i) {
22949 final UidRecord uidRec = mActiveUids.valueAt(i);
22950 // If the network is not restricted for uid, then nothing to do here.
22951 if (!mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
22952 continue;
22953 }
22954 if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
22955 continue;
22956 }
22957 // If process state is not changed, then there's nothing to do.
22958 if (uidRec.setProcState == uidRec.curProcState) {
22959 continue;
22960 }
22961 final int blockState = getBlockStateForUid(uidRec);
22962 // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
22963 // there's nothing the app needs to do in this scenario.
22964 if (blockState == NETWORK_STATE_NO_CHANGE) {
22965 continue;
22966 }
22967 synchronized (uidRec.networkStateLock) {
22968 uidRec.curProcStateSeq = ++mProcStateSeqCounter;
22969 if (blockState == NETWORK_STATE_BLOCK) {
22970 if (blockingUids == null) {
22971 blockingUids = new ArrayList<>();
22972 }
22973 blockingUids.add(uidRec.uid);
22974 } else {
22975 if (DEBUG_NETWORK) {
22976 Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
22977 + " threads for uid: " + uidRec);
22978 }
22979 if (uidRec.waitingForNetwork) {
22980 uidRec.networkStateLock.notifyAll();
22981 }
22982 }
22983 }
22984 }
22985
22986 // There are no uids that need to block, so nothing more to do.
22987 if (blockingUids == null) {
22988 return;
22989 }
22990
22991 for (int i = mLruProcesses.size() - 1; i >= 0; --i) {
22992 final ProcessRecord app = mLruProcesses.get(i);
22993 if (!blockingUids.contains(app.uid)) {
22994 continue;
22995 }
22996 if (!app.killedByAm && app.thread != null) {
22997 final UidRecord uidRec = mActiveUids.get(app.uid);
22998 try {
22999 if (DEBUG_NETWORK) {
23000 Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
23001 + uidRec);
23002 }
23003 app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
23004 } catch (RemoteException ignored) {
23005 }
23006 }
23007 }
23008 }
23009
23010 /**
23011 * Checks if the uid is coming from background to foreground or vice versa and returns
23012 * appropriate block state based on this.
23013 *
23014 * @return blockState based on whether the uid is coming from background to foreground or
23015 * vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
23016 * {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
23017 * {@link #NETWORK_STATE_NO_CHANGE}.
23018 */
23019 @VisibleForTesting
23020 int getBlockStateForUid(UidRecord uidRec) {
23021 // Denotes whether uid's process state is currently allowed network access.
23022 final boolean isAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.curProcState)
23023 || isProcStateAllowedWhileOnRestrictBackground(uidRec.curProcState);
23024 // Denotes whether uid's process state was previously allowed network access.
23025 final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
23026 || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
23027
23028 // When the uid is coming to foreground, AMS should inform the app thread that it should
23029 // block for the network rules to get updated before launching an activity.
23030 if (!wasAllowed && isAllowed) {
23031 return NETWORK_STATE_BLOCK;
23032 }
23033 // When the uid is going to background, AMS should inform the app thread that if an
23034 // activity launch is blocked for the network rules to get updated, it should be unblocked.
23035 if (wasAllowed && !isAllowed) {
23036 return NETWORK_STATE_UNBLOCK;
23037 }
23038 return NETWORK_STATE_NO_CHANGE;
23039 }
23040
23041 final void runInBackgroundDisabled(int uid) {
23042 synchronized (this) {
23043 UidRecord uidRec = mActiveUids.get(uid);
23044 if (uidRec != null) {
23045 // This uid is actually running... should it be considered background now?
23046 if (uidRec.idle) {
23047 doStopUidLocked(uidRec.uid, uidRec);
23048 }
23049 } else {
23050 // This uid isn't actually running... still send a report about it being "stopped".
23051 doStopUidLocked(uid, null);
23052 }
23053 }
23054 }
23055
23056 final void doStopUidLocked(int uid, final UidRecord uidRec) {
23057 mServices.stopInBackgroundLocked(uid);
23058 enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE);
23059 }
23060
23061 /**
23062 * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
23063 */
23064 void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
23065 long duration, String tag) {
23066 if (DEBUG_WHITELISTS) {
23067 Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
23068 + targetUid + ", " + duration + ")");
23069 }
23070
23071 synchronized (mPidsSelfLocked) {
23072 final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
23073 if (pr == null) {
23074 Slog.w(TAG, "tempWhitelistForPendingIntentLocked() no ProcessRecord for pid "
23075 + callerPid);
23076 return;
23077 }
23078 if (!pr.whitelistManager) {
23079 if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
23080 != PackageManager.PERMISSION_GRANTED) {
23081 if (DEBUG_WHITELISTS) {
23082 Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid
23083 + ": pid " + callerPid + " is not allowed");
23084 }
23085 return;
23086 }
23087 }
23088 }
23089
23090 tempWhitelistUidLocked(targetUid, duration, tag);
23091 }
23092
23093 /**
23094 * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
23095 */
23096 void tempWhitelistUidLocked(int targetUid, long duration, String tag) {
23097 mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag));
23098 setUidTempWhitelistStateLocked(targetUid, true);
23099 mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget();
23100 }
23101
23102 void pushTempWhitelist() {
23103 final int N;
23104 final PendingTempWhitelist[] list;
23105
23106 // First copy out the pending changes... we need to leave them in the map for now,
23107 // in case someone needs to check what is coming up while we don't have the lock held.
23108 synchronized(this) {
23109 N = mPendingTempWhitelist.size();
23110 list = new PendingTempWhitelist[N];
23111 for (int i = 0; i < N; i++) {
23112 list[i] = mPendingTempWhitelist.valueAt(i);
23113 }
23114 }
23115
23116 // Now safely dispatch changes to device idle controller.
23117 for (int i = 0; i < N; i++) {
23118 PendingTempWhitelist ptw = list[i];
23119 mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid,
23120 ptw.duration, true, ptw.tag);
23121 }
23122
23123 // And now we can safely remove them from the map.
23124 synchronized(this) {
23125 for (int i = 0; i < N; i++) {
23126 PendingTempWhitelist ptw = list[i];
23127 int index = mPendingTempWhitelist.indexOfKey(ptw.targetUid);
23128 if (index >= 0 && mPendingTempWhitelist.valueAt(index) == ptw) {
23129 mPendingTempWhitelist.removeAt(index);
23130 }
23131 }
23132 }
23133 }
23134
23135 final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
23136 boolean changed = false;
23137 for (int i=mActiveUids.size()-1; i>=0; i--) {
23138 final UidRecord uidRec = mActiveUids.valueAt(i);
23139 if (UserHandle.getAppId(uidRec.uid) == appId && uidRec.curWhitelist != onWhitelist) {
23140 uidRec.curWhitelist = onWhitelist;
23141 changed = true;
23142 }
23143 }
23144 if (changed) {
23145 updateOomAdjLocked();
23146 }
23147 }
23148
23149 final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) {
23150 boolean changed = false;
23151 final UidRecord uidRec = mActiveUids.get(uid);
23152 if (uidRec != null && uidRec.curWhitelist != onWhitelist) {
23153 uidRec.curWhitelist = onWhitelist;
23154 updateOomAdjLocked();
23155 }
23156 }
23157
23158 final void trimApplications() {
23159 synchronized (this) {
23160 int i;
23161
23162 // First remove any unused application processes whose package
23163 // has been removed.
23164 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
23165 final ProcessRecord app = mRemovedProcesses.get(i);
23166 if (app.activities.size() == 0
23167 && app.curReceivers.isEmpty() && app.services.size() == 0) {
23168 Slog.i(
23169 TAG, "Exiting empty application process "
23170 + app.toShortString() + " ("
23171 + (app.thread != null ? app.thread.asBinder() : null)
23172 + ")\n");
23173 if (app.pid > 0 && app.pid != MY_PID) {
23174 app.kill("empty", false);
23175 } else {
23176 try {
23177 app.thread.scheduleExit();
23178 } catch (Exception e) {
23179 // Ignore exceptions.
23180 }
23181 }
23182 cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
23183 mRemovedProcesses.remove(i);
23184
23185 if (app.persistent) {
23186 addAppLocked(app.info, null, false, null /* ABI override */);
23187 }
23188 }
23189 }
23190
23191 // Now update the oom adj for all processes.
23192 updateOomAdjLocked();
23193 }
23194 }
23195
23196 /** This method sends the specified signal to each of the persistent apps */
23197 public void signalPersistentProcesses(int sig) throws RemoteException {
23198 if (sig != SIGNAL_USR1) {
23199 throw new SecurityException("Only SIGNAL_USR1 is allowed");
23200 }
23201
23202 synchronized (this) {
23203 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
23204 != PackageManager.PERMISSION_GRANTED) {
23205 throw new SecurityException("Requires permission "
23206 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
23207 }
23208
23209 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
23210 ProcessRecord r = mLruProcesses.get(i);
23211 if (r.thread != null && r.persistent) {
23212 sendSignal(r.pid, sig);
23213 }
23214 }
23215 }
23216 }

profile操作相关

 23218    private void stopProfilerLocked(ProcessRecord proc, int profileType) {
23219 if (proc == null || proc == mProfileProc) {
23220 proc = mProfileProc;
23221 profileType = mProfileType;
23222 clearProfilerLocked();
23223 }
23224 if (proc == null) {
23225 return;
23226 }
23227 try {
23228 proc.thread.profilerControl(false, null, profileType);
23229 } catch (RemoteException e) {
23230 throw new IllegalStateException("Process disappeared");
23231 }
23232 }
23233
23234 private void clearProfilerLocked() {
23235 if (mProfileFd != null) {
23236 try {
23237 mProfileFd.close();
23238 } catch (IOException e) {
23239 }
23240 }
23241 mProfileApp = null;
23242 mProfileProc = null;
23243 mProfileFile = null;
23244 mProfileType = 0;
23245 mAutoStopProfiler = false;
23246 mStreamingOutput = false;
23247 mSamplingInterval = 0;
23248 }
23249
23250 public boolean profileControl(String process, int userId, boolean start,
23251 ProfilerInfo profilerInfo, int profileType) throws RemoteException {
23252
23253 try {
23254 synchronized (this) {
23255 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
23256 // its own permission.
23257 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
23258 != PackageManager.PERMISSION_GRANTED) {
23259 throw new SecurityException("Requires permission "
23260 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
23261 }
23262
23263 if (start && (profilerInfo == null || profilerInfo.profileFd == null)) {
23264 throw new IllegalArgumentException("null profile info or fd");
23265 }
23266
23267 ProcessRecord proc = null;
23268 if (process != null) {
23269 proc = findProcessLocked(process, userId, "profileControl");
23270 }
23271
23272 if (start && (proc == null || proc.thread == null)) {
23273 throw new IllegalArgumentException("Unknown process: " + process);
23274 }
23275
23276 if (start) {
23277 stopProfilerLocked(null, 0);
23278 setProfileApp(proc.info, proc.processName, profilerInfo);
23279 mProfileProc = proc;
23280 mProfileType = profileType;
23281 ParcelFileDescriptor fd = profilerInfo.profileFd;
23282 try {
23283 fd = fd.dup();
23284 } catch (IOException e) {
23285 fd = null;
23286 }
23287 profilerInfo.profileFd = fd;
23288 proc.thread.profilerControl(start, profilerInfo, profileType);
23289 fd = null;
23290 try {
23291 mProfileFd.close();
23292 } catch (IOException e) {
23293 }
23294 mProfileFd = null;
23295 } else {
23296 stopProfilerLocked(proc, profileType);
23297 if (profilerInfo != null && profilerInfo.profileFd != null) {
23298 try {
23299 profilerInfo.profileFd.close();
23300 } catch (IOException e) {
23301 }
23302 }
23303 }
23304
23305 return true;
23306 }
23307 } catch (RemoteException e) {
23308 throw new IllegalStateException("Process disappeared");
23309 } finally {
23310 if (profilerInfo != null && profilerInfo.profileFd != null) {
23311 try {
23312 profilerInfo.profileFd.close();
23313 } catch (IOException e) {
23314 }
23315 }
23316 }
23317 }

找到进程

 23319    private ProcessRecord findProcessLocked(String process, int userId, String callName) {
23320 userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
23321 userId, true, ALLOW_FULL_ONLY, callName, null);
23322 ProcessRecord proc = null;
23323 try {
23324 int pid = Integer.parseInt(process);
23325 synchronized (mPidsSelfLocked) {
23326 proc = mPidsSelfLocked.get(pid);
23327 }
23328 } catch (NumberFormatException e) {
23329 }
23330
23331 if (proc == null) {
23332 ArrayMap<String, SparseArray<ProcessRecord>> all
23333 = mProcessNames.getMap();
23334 SparseArray<ProcessRecord> procs = all.get(process);
23335 if (procs != null && procs.size() > 0) {
23336 proc = procs.valueAt(0);
23337 if (userId != UserHandle.USER_ALL && proc.userId != userId) {
23338 for (int i=1; i<procs.size(); i++) {
23339 ProcessRecord thisProc = procs.valueAt(i);
23340 if (thisProc.userId == userId) {
23341 proc = thisProc;
23342 break;
23343 }
23344 }
23345 }
23346 }
23347 }
23348
23349 return proc;
23350 }

dump heap

 23352    public boolean dumpHeap(String process, int userId, boolean managed,
23353 String path, ParcelFileDescriptor fd) throws RemoteException {
23354
23355 try {
23356 synchronized (this) {
23357 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
23358 // its own permission (same as profileControl).
23359 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
23360 != PackageManager.PERMISSION_GRANTED) {
23361 throw new SecurityException("Requires permission "
23362 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
23363 }
23364
23365 if (fd == null) {
23366 throw new IllegalArgumentException("null fd");
23367 }
23368
23369 ProcessRecord proc = findProcessLocked(process, userId, "dumpHeap");
23370 if (proc == null || proc.thread == null) {
23371 throw new IllegalArgumentException("Unknown process: " + process);
23372 }
23373
23374 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
23375 if (!isDebuggable) {
23376 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
23377 throw new SecurityException("Process not debuggable: " + proc);
23378 }
23379 }
23380
23381 proc.thread.dumpHeap(managed, path, fd);
23382 fd = null;
23383 return true;
23384 }
23385 } catch (RemoteException e) {
23386 throw new IllegalStateException("Process disappeared");
23387 } finally {
23388 if (fd != null) {
23389 try {
23390 fd.close();
23391 } catch (IOException e) {
23392 }
23393 }
23394 }
23395 }
23396
23397 @Override
23398 public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
23399 String reportPackage) {
23400 if (processName != null) {
23401 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
23402 "setDumpHeapDebugLimit()");
23403 } else {
23404 synchronized (mPidsSelfLocked) {
23405 ProcessRecord proc = mPidsSelfLocked.get(Binder.getCallingPid());
23406 if (proc == null) {
23407 throw new SecurityException("No process found for calling pid "
23408 + Binder.getCallingPid());
23409 }
23410 if (!Build.IS_DEBUGGABLE
23411 && (proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
23412 throw new SecurityException("Not running a debuggable build");
23413 }
23414 processName = proc.processName;
23415 uid = proc.uid;
23416 if (reportPackage != null && !proc.pkgList.containsKey(reportPackage)) {
23417 throw new SecurityException("Package " + reportPackage + " is not running in "
23418 + proc);
23419 }
23420 }
23421 }
23422 synchronized (this) {
23423 if (maxMemSize > 0) {
23424 mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage));
23425 } else {
23426 if (uid != 0) {
23427 mMemWatchProcesses.remove(processName, uid);
23428 } else {
23429 mMemWatchProcesses.getMap().remove(processName);
23430 }
23431 }
23432 }
23433 }
23434
23435 @Override
23436 public void dumpHeapFinished(String path) {
23437 synchronized (this) {
23438 if (Binder.getCallingPid() != mMemWatchDumpPid) {
23439 Slog.w(TAG, "dumpHeapFinished: Calling pid " + Binder.getCallingPid()
23440 + " does not match last pid " + mMemWatchDumpPid);
23441 return;
23442 }
23443 if (mMemWatchDumpFile == null || !mMemWatchDumpFile.equals(path)) {
23444 Slog.w(TAG, "dumpHeapFinished: Calling path " + path
23445 + " does not match last path " + mMemWatchDumpFile);
23446 return;
23447 }
23448 if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
23449 mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
23450 }
23451 }
23452

monitor

 23453    /** In this method we try to acquire our lock to make sure that we have not deadlocked */
23454 public void monitor() {
23455 synchronized (this) { }
23456 }
23457

核心设置改变回调

 23458    void onCoreSettingsChange(Bundle settings) {
23459 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
23460 ProcessRecord processRecord = mLruProcesses.get(i);
23461 try {
23462 if (processRecord.thread != null) {
23463 processRecord.thread.setCoreSettings(settings);
23464 }
23465 } catch (RemoteException re) {
23466 /* ignore */
23467 }
23468

多用户相关

 23471    // Multi-user methods
23472
23473 /**
23474 * Start user, if its not already running, but don't bring it to foreground.
23475 */
23476 @Override
23477 public boolean startUserInBackground(final int userId) {
23478 return mUserController.startUser(userId, /* foreground */ false);
23479 }
23480
23481 @Override
23482 public boolean unlockUser(int userId, byte[] token, byte[] secret, IProgressListener listener) {
23483 return mUserController.unlockUser(userId, token, secret, listener);
23484 }
23485
23486 @Override
23487 public boolean switchUser(final int targetUserId) {
23488 enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
23489 int currentUserId;
23490 UserInfo targetUserInfo;
23491 synchronized (this) {
23492 currentUserId = mUserController.getCurrentUserIdLocked();
23493 targetUserInfo = mUserController.getUserInfo(targetUserId);
23494 if (targetUserId == currentUserId) {
23495 Slog.i(TAG, "user #" + targetUserId + " is already the current user");
23496 return true;
23497 }
23498 if (targetUserInfo == null) {
23499 Slog.w(TAG, "No user info for user #" + targetUserId);
23500 return false;
23501 }
23502 if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mContext)) {
23503 Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId
23504 + " when device is in demo mode");
23505 return false;
23506 }
23507 if (!targetUserInfo.supportsSwitchTo()) {
23508 Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
23509 return false;
23510 }
23511 if (targetUserInfo.isManagedProfile()) {
23512 Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
23513 return false;
23514 }
23515 mUserController.setTargetUserIdLocked(targetUserId);
23516 }
23517 if (mUserController.mUserSwitchUiEnabled) {
23518 UserInfo currentUserInfo = mUserController.getUserInfo(currentUserId);
23519 Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo);
23520 mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG);
23521 mUiHandler.sendMessage(mHandler.obtainMessage(
23522 START_USER_SWITCH_UI_MSG, userNames));
23523 } else {
23524 mHandler.removeMessages(START_USER_SWITCH_FG_MSG);
23525 mHandler.sendMessage(mHandler.obtainMessage(
23526 START_USER_SWITCH_FG_MSG, targetUserId, 0));
23527 }
23528 return true;
23529 }
23530
23531 void scheduleStartProfilesLocked() {
23532 if (!mHandler.hasMessages(START_PROFILES_MSG)) {
23533 mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
23534 DateUtils.SECOND_IN_MILLIS);
23535 }
23536 }
23537
23538 @Override
23539 public int stopUser(final int userId, boolean force, final IStopUserCallback callback) {
23540 return mUserController.stopUser(userId, force, callback);
23541 }
23542
23543 @Override
23544 public UserInfo getCurrentUser() {
23545 return mUserController.getCurrentUser();
23546 }
23547
23548 String getStartedUserState(int userId) {
23549 synchronized (this) {
23550 final UserState userState = mUserController.getStartedUserStateLocked(userId);
23551 return UserState.stateToString(userState.state);
23552 }
23553 }
23554
23555 @Override
23556 public boolean isUserRunning(int userId, int flags) {
23557 if (!mUserController.isSameProfileGroup(userId, UserHandle.getCallingUserId())
23558 && checkCallingPermission(INTERACT_ACROSS_USERS)
23559 != PackageManager.PERMISSION_GRANTED) {
23560 String msg = "Permission Denial: isUserRunning() from pid="
23561 + Binder.getCallingPid()
23562 + ", uid=" + Binder.getCallingUid()
23563 + " requires " + INTERACT_ACROSS_USERS;
23564 Slog.w(TAG, msg);
23565 throw new SecurityException(msg);
23566 }
23567 synchronized (this) {
23568 return mUserController.isUserRunningLocked(userId, flags);
23569 }
23570 }
23571
23572 @Override
23573 public int[] getRunningUserIds() {
23574 if (checkCallingPermission(INTERACT_ACROSS_USERS)
23575 != PackageManager.PERMISSION_GRANTED) {
23576 String msg = "Permission Denial: isUserRunning() from pid="
23577 + Binder.getCallingPid()
23578 + ", uid=" + Binder.getCallingUid()
23579 + " requires " + INTERACT_ACROSS_USERS;
23580 Slog.w(TAG, msg);
23581 throw new SecurityException(msg);
23582 }
23583 synchronized (this) {
23584 return mUserController.getStartedUserArrayLocked();
23585 }
23586 }
23587
23588 @Override
23589 public void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
23590 mUserController.registerUserSwitchObserver(observer, name);
23591 }
23592
23593 @Override
23594 public void unregisterUserSwitchObserver(IUserSwitchObserver observer) {
23595 mUserController.unregisterUserSwitchObserver(observer);
23596 }
23597
23598 ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
23599 if (info == null) return null;
23600 ApplicationInfo newInfo = new ApplicationInfo(info);
23601 newInfo.initForUser(userId);
23602 return newInfo;
23603 }
23604
23605 public boolean isUserStopped(int userId) {
23606 synchronized (this) {
23607 return mUserController.getStartedUserStateLocked(userId) == null;
23608 }
23609 }
23610
23611 ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
23612 if (aInfo == null
23613 || (userId < 1 && aInfo.applicationInfo.uid < UserHandle.PER_USER_RANGE)) {
23614 return aInfo;
23615 }
23616
23617 ActivityInfo info = new ActivityInfo(aInfo);
23618 info.applicationInfo = getAppInfoForUser(info.applicationInfo, userId);
23619 return info;
23620 }

开始、结束bind track

 23637    public boolean startBinderTracking() throws RemoteException {
23638 synchronized (this) {
23639 mBinderTransactionTrackingEnabled = true;
23640 // TODO: hijacking SET_ACTIVITY_WATCHER, but should be changed to its own
23641 // permission (same as profileControl).
23642 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
23643 != PackageManager.PERMISSION_GRANTED) {
23644 throw new SecurityException("Requires permission "
23645 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
23646 }
23647
23648 for (int i = 0; i < mLruProcesses.size(); i++) {
23649 ProcessRecord process = mLruProcesses.get(i);
23650 if (!processSanityChecksLocked(process)) {
23651 continue;
23652 }
23653 try {
23654 process.thread.startBinderTracking();
23655 } catch (RemoteException e) {
23656 Log.v(TAG, "Process disappared");
23657 }
23658 }
23659 return true;
23660 }
23661 }
23662
23663 public boolean stopBinderTrackingAndDump(ParcelFileDescriptor fd) throws RemoteException {
23664 try {
23665 synchronized (this) {
23666 mBinderTransactionTrackingEnabled = false;
23667 // TODO: hijacking SET_ACTIVITY_WATCHER, but should be changed to its own
23668 // permission (same as profileControl).
23669 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
23670 != PackageManager.PERMISSION_GRANTED) {
23671 throw new SecurityException("Requires permission "
23672 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
23673 }
23674
23675 if (fd == null) {
23676 throw new IllegalArgumentException("null fd");
23677 }
23678
23679 PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd.getFileDescriptor()));
23680 pw.println("Binder transaction traces for all processes.\n");
23681 for (ProcessRecord process : mLruProcesses) {
23682 if (!processSanityChecksLocked(process)) {
23683 continue;
23684 }
23685
23686 pw.println("Traces for process: " + process.processName);
23687 pw.flush();
23688 try {
23689 TransferPipe tp = new TransferPipe();
23690 try {
23691 process.thread.stopBinderTrackingAndDump(tp.getWriteFd());
23692 tp.go(fd.getFileDescriptor());
23693 } finally {
23694 tp.kill();
23695 }
23696 } catch (IOException e) {
23697 pw.println("Failure while dumping IPC traces from " + process +
23698 ". Exception: " + e);
23699 pw.flush();
23700 } catch (RemoteException e) {
23701 pw.println("Got a RemoteException while dumping IPC traces from " +
23702 process + ". Exception: " + e);
23703 pw.flush();
23704 }
23705 }
23706 fd = null;
23707 return true;
23708 }
23709 } finally {
23710 if (fd != null) {
23711 try {
23712 fd.close();
23713 } catch (IOException e) {
23714 }
23715 }
23716 }
23717 }

内部类LocalService实现了ActivityManagerInternal的方法

 23719    @VisibleForTesting
23720 final class LocalService extends ActivityManagerInternal {
23721 @Override
23722 public void grantUriPermissionFromIntent(int callingUid, String targetPkg, Intent intent,
23723 int targetUserId) {
23724 synchronized (ActivityManagerService.this) {
23725 ActivityManagerService.this.grantUriPermissionFromIntentLocked(callingUid,
23726 targetPkg, intent, null, targetUserId);
23727 }
23728 }
23729
23730 @Override
23731 public String checkContentProviderAccess(String authority, int userId) {
23732 return ActivityManagerService.this.checkContentProviderAccess(authority, userId);
23733 }
23734
23735 @Override
23736 public void onWakefulnessChanged(int wakefulness) {
23737 ActivityManagerService.this.onWakefulnessChanged(wakefulness);
23738 }
23739
23740 @Override
23741 public int startIsolatedProcess(String entryPoint, String[] entryPointArgs,
23742 String processName, String abiOverride, int uid, Runnable crashHandler) {
23743 return ActivityManagerService.this.startIsolatedProcess(entryPoint, entryPointArgs,
23744 processName, abiOverride, uid, crashHandler);
23745 }
23746
23747 @Override
23748 public SleepToken acquireSleepToken(String tag) {
23749 Preconditions.checkNotNull(tag);
23750
23751 synchronized (ActivityManagerService.this) {
23752 SleepTokenImpl token = new SleepTokenImpl(tag);
23753 mSleepTokens.add(token);
23754 updateSleepIfNeededLocked();
23755 return token;
23756 }
23757 }
23758
23759 @Override
23760 public ComponentName getHomeActivityForUser(int userId) {
23761 synchronized (ActivityManagerService.this) {
23762 ActivityRecord homeActivity = mStackSupervisor.getHomeActivityForUser(userId);
23763 return homeActivity == null ? null : homeActivity.realActivity;
23764 }
23765 }
23766
23767 @Override
23768 public void onUserRemoved(int userId) {
23769 synchronized (ActivityManagerService.this) {
23770 ActivityManagerService.this.onUserStoppedLocked(userId);
23771 }
23772 }
23773
23774 @Override
23775 public void onLocalVoiceInteractionStarted(IBinder activity,
23776 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
23777 synchronized (ActivityManagerService.this) {
23778 ActivityManagerService.this.onLocalVoiceInteractionStartedLocked(activity,
23779 voiceSession, voiceInteractor);
23780 }
23781 }
23782
23783 @Override
23784 public void notifyAppTransitionStarting(SparseIntArray reasons, long timestamp) {
23785 synchronized (ActivityManagerService.this) {
23786 mStackSupervisor.mActivityMetricsLogger.notifyTransitionStarting(
23787 reasons, timestamp);
23788 }
23789 }
23790
23791 @Override
23792 public void notifyAppTransitionFinished() {
23793 synchronized (ActivityManagerService.this) {
23794 mStackSupervisor.notifyAppTransitionDone();
23795 }
23796 }
23797
23798 @Override
23799 public void notifyAppTransitionCancelled() {
23800 synchronized (ActivityManagerService.this) {
23801 mStackSupervisor.notifyAppTransitionDone();
23802 }
23803 }
23804
23805 @Override
23806 public List<IBinder> getTopVisibleActivities() {
23807 synchronized (ActivityManagerService.this) {
23808 return mStackSupervisor.getTopVisibleActivities();
23809 }
23810 }
23811
23812 @Override
23813 public void notifyDockedStackMinimizedChanged(boolean minimized) {
23814 synchronized (ActivityManagerService.this) {
23815 mStackSupervisor.setDockedStackMinimized(minimized);
23816 }
23817 }
23818
23819 @Override
23820 public void killForegroundAppsForUser(int userHandle) {
23821 synchronized (ActivityManagerService.this) {
23822 final ArrayList<ProcessRecord> procs = new ArrayList<>();
23823 final int NP = mProcessNames.getMap().size();
23824 for (int ip = 0; ip < NP; ip++) {
23825 final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
23826 final int NA = apps.size();
23827 for (int ia = 0; ia < NA; ia++) {
23828 final ProcessRecord app = apps.valueAt(ia);
23829 if (app.persistent) {
23830 // We don't kill persistent processes.
23831 continue;
23832 }
23833 if (app.removed) {
23834 procs.add(app);
23835 } else if (app.userId == userHandle && app.foregroundActivities) {
23836 app.removed = true;
23837 procs.add(app);
23838 }
23839 }
23840 }
23841
23842 final int N = procs.size();
23843 for (int i = 0; i < N; i++) {
23844 removeProcessLocked(procs.get(i), false, true, "kill all fg");
23845 }
23846 }
23847 }
23848
23849 @Override
23850 public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
23851 long duration) {
23852 if (!(target instanceof PendingIntentRecord)) {
23853 Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
23854 return;
23855 }
23856 ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
23857 }
23858
23859 @Override
23860 public void setDeviceIdleWhitelist(int[] appids) {
23861 synchronized (ActivityManagerService.this) {
23862 mDeviceIdleWhitelist = appids;
23863 }
23864 }
23865
23866 @Override
23867 public void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, boolean adding) {
23868 synchronized (ActivityManagerService.this) {
23869 mDeviceIdleTempWhitelist = appids;
23870 setAppIdTempWhitelistStateLocked(changingAppId, adding);
23871 }
23872 }
23873
23874 @Override
23875 public void updatePersistentConfigurationForUser(@NonNull Configuration values,
23876 int userId) {
23877 Preconditions.checkNotNull(values, "Configuration must not be null");
23878 Preconditions.checkArgumentNonnegative(userId, "userId " + userId + " not supported");
23879 synchronized (ActivityManagerService.this) {
23880 updateConfigurationLocked(values, null, false, true, userId,
23881 false /* deferResume */);
23882 }
23883 }
23884
23885 @Override
23886 public int startActivitiesAsPackage(String packageName, int userId, Intent[] intents,
23887 Bundle bOptions) {
23888 Preconditions.checkNotNull(intents, "intents");
23889 final String[] resolvedTypes = new String[intents.length];
23890 for (int i = 0; i < intents.length; i++) {
23891 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(mContext.getContentResolver());
23892 }
23893
23894 // UID of the package on user userId.
23895 // "= 0" is needed because otherwise catch(RemoteException) would make it look like
23896 // packageUid may not be initialized.
23897 int packageUid = 0;
23898 try {
23899 packageUid = AppGlobals.getPackageManager().getPackageUid(
23900 packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
23901 } catch (RemoteException e) {
23902 // Shouldn't happen.
23903 }
23904
23905 synchronized (ActivityManagerService.this) {
23906 return startActivitiesInPackage(packageUid, packageName, intents, resolvedTypes,
23907 /*resultTo*/ null, bOptions, userId);
23908 }
23909 }
23910
23911 @Override
23912 public int getUidProcessState(int uid) {
23913 return getUidState(uid);
23914 }
23915
23916 @Override
23917 public void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
23918 synchronized (ActivityManagerService.this) {
23919
23920 // We might change the visibilities here, so prepare an empty app transition which
23921 // might be overridden later if we actually change visibilities.
23922 mWindowManager.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
23923 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
23924 mWindowManager.executeAppTransition();
23925 }
23926 if (callback != null) {
23927 callback.run();
23928 }
23929 }
23930
23931 @Override
23932 public boolean isSystemReady() {
23933 // no need to synchronize(this) just to read & return the value
23934 return mSystemReady;
23935 }
23936
23937 @Override
23938 public void notifyKeyguardTrustedChanged() {
23939 synchronized (ActivityManagerService.this) {
23940 if (mKeyguardController.isKeyguardShowing()) {
23941 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
23942 }
23943 }
23944 }
23945
23946 /**
23947 * Sets if the given pid has an overlay UI or not.
23948 *
23949 * @param pid The pid we are setting overlay UI for.
23950 * @param hasOverlayUi True if the process has overlay UI.
23951 * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
23952 */
23953 @Override
23954 public void setHasOverlayUi(int pid, boolean hasOverlayUi) {
23955 synchronized (ActivityManagerService.this) {
23956 final ProcessRecord pr;
23957 synchronized (mPidsSelfLocked) {
23958 pr = mPidsSelfLocked.get(pid);
23959 if (pr == null) {
23960 Slog.w(TAG, "setHasOverlayUi called on unknown pid: " + pid);
23961 return;
23962 }
23963 }
23964 if (pr.hasOverlayUi == hasOverlayUi) {
23965 return;
23966 }
23967 pr.hasOverlayUi = hasOverlayUi;
23968 //Slog.i(TAG, "Setting hasOverlayUi=" + pr.hasOverlayUi + " for pid=" + pid);
23969 updateOomAdjLocked(pr, true);
23970 }
23971 }
23972
23973 /**
23974 * Called after the network policy rules are updated by
23975 * {@link com.android.server.net.NetworkPolicyManagerService} for a specific {@param uid}
23976 * and {@param procStateSeq}.
23977 */
23978 @Override
23979 public void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq) {
23980 if (DEBUG_NETWORK) {
23981 Slog.d(TAG_NETWORK, "Got update from NPMS for uid: "
23982 + uid + " seq: " + procStateSeq);
23983 }
23984 UidRecord record;
23985 synchronized (ActivityManagerService.this) {
23986 record = mActiveUids.get(uid);
23987 if (record == null) {
23988 if (DEBUG_NETWORK) {
23989 Slog.d(TAG_NETWORK, "No active uidRecord for uid: " + uid
23990 + " procStateSeq: " + procStateSeq);
23991 }
23992 return;
23993 }
23994 }
23995 synchronized (record.networkStateLock) {
23996 if (record.lastNetworkUpdatedProcStateSeq >= procStateSeq) {
23997 if (DEBUG_NETWORK) {
23998 Slog.d(TAG_NETWORK, "procStateSeq: " + procStateSeq + " has already"
23999 + " been handled for uid: " + uid);
24000 }
24001 return;
24002 }
24003 record.lastNetworkUpdatedProcStateSeq = procStateSeq;
24004 if (record.curProcStateSeq > procStateSeq) {
24005 if (DEBUG_NETWORK) {
24006 Slog.d(TAG_NETWORK, "No need to handle older seq no., Uid: " + uid
24007 + ", curProcstateSeq: " + record.curProcStateSeq
24008 + ", procStateSeq: " + procStateSeq);
24009 }
24010 return;
24011 }
24012 if (record.waitingForNetwork) {
24013 if (DEBUG_NETWORK) {
24014 Slog.d(TAG_NETWORK, "Notifying all blocking threads for uid: " + uid
24015 + ", procStateSeq: " + procStateSeq);
24016 }
24017 record.networkStateLock.notifyAll();
24018 }
24019 }
24020 }

等待网络状态更新,等待广播idle

 24069    /**
24070 * Called by app main thread to wait for the network policy rules to get updated.
24071 *
24072 * @param procStateSeq The sequence number indicating the process state change that the main
24073 * thread is interested in.
24074 */
24075 @Override
24076 public void waitForNetworkStateUpdate(long procStateSeq) {
24077 final int callingUid = Binder.getCallingUid();
24078 if (DEBUG_NETWORK) {
24079 Slog.d(TAG_NETWORK, "Called from " + callingUid + " to wait for seq: " + procStateSeq);
24080 }
24081 UidRecord record;
24082 synchronized (this) {
24083 record = mActiveUids.get(callingUid);
24084 if (record == null) {
24085 return;
24086 }
24087 }
24088 synchronized (record.networkStateLock) {
24089 if (record.lastDispatchedProcStateSeq < procStateSeq) {
24090 if (DEBUG_NETWORK) {
24091 Slog.d(TAG_NETWORK, "Uid state change for seq no. " + procStateSeq + " is not "
24092 + "dispatched to NPMS yet, so don't wait. Uid: " + callingUid
24093 + " lastProcStateSeqDispatchedToObservers: "
24094 + record.lastDispatchedProcStateSeq);
24095 }
24096 return;
24097 }
24098 if (record.curProcStateSeq > procStateSeq) {
24099 if (DEBUG_NETWORK) {
24100 Slog.d(TAG_NETWORK, "Ignore the wait requests for older seq numbers. Uid: "
24101 + callingUid + ", curProcStateSeq: " + record.curProcStateSeq
24102 + ", procStateSeq: " + procStateSeq);
24103 }
24104 return;
24105 }
24106 if (record.lastNetworkUpdatedProcStateSeq >= procStateSeq) {
24107 if (DEBUG_NETWORK) {
24108 Slog.d(TAG_NETWORK, "Network rules have been already updated for seq no. "
24109 + procStateSeq + ", so no need to wait. Uid: "
24110 + callingUid + ", lastProcStateSeqWithUpdatedNetworkState: "
24111 + record.lastNetworkUpdatedProcStateSeq);
24112 }
24113 return;
24114 }
24115 try {
24116 if (DEBUG_NETWORK) {
24117 Slog.d(TAG_NETWORK, "Starting to wait for the network rules update."
24118 + " Uid: " + callingUid + " procStateSeq: " + procStateSeq);
24119 }
24120 final long startTime = SystemClock.uptimeMillis();
24121 record.waitingForNetwork = true;
24122 record.networkStateLock.wait(mWaitForNetworkTimeoutMs);
24123 record.waitingForNetwork = false;
24124 final long totalTime = SystemClock.uptimeMillis() - startTime;
24125 if (totalTime >= mWaitForNetworkTimeoutMs) {
24126 Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: "
24127 + totalTime + ". Uid: " + callingUid + " procStateSeq: "
24128 + procStateSeq + " UidRec: " + record
24129 + " validateUidRec: " + mValidateUids.get(callingUid));
24130 }
24131 } catch (InterruptedException e) {
24132 Thread.currentThread().interrupt();
24133 }
24134 }
24135 }
24136
24137 public void waitForBroadcastIdle(PrintWriter pw) {
24138 enforceCallingPermission(permission.DUMP, "waitForBroadcastIdle()");
24139 while (true) {
24140 boolean idle = true;
24141 synchronized (this) {
24142 for (BroadcastQueue queue : mBroadcastQueues) {
24143 if (!queue.isIdle()) {
24144 final String msg = "Waiting for queue " + queue + " to become idle...";
24145 pw.println(msg);
24146 pw.flush();
24147 Slog.v(TAG, msg);
24148 idle = false;
24149 }
24150 }
24151 }
24152
24153 if (idle) {
24154 final String msg = "All broadcast queues are idle!";
24155 pw.println(msg);
24156 pw.flush();
24157 Slog.v(TAG, msg);
24158 return;
24159 } else {
24160 SystemClock.sleep(1000);
24161 }
24162 }
24163 }

获取上次resumed的activity user id

 24165    /**
24166 * Return the user id of the last resumed activity.
24167 */
24168 @Override
24169 public @UserIdInt int getLastResumedActivityUserId() {
24170 enforceCallingPermission(
24171 permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
24172 synchronized (this) {
24173 if (mLastResumedActivity == null) {
24174 return mUserController.getCurrentUserIdLocked();
24175 }
24176 return mLastResumedActivity.userId;
24177 }
24178 }
24179

内部类,睡眠token

 24180    private final class SleepTokenImpl extends SleepToken {
24181 private final String mTag;
24182 private final long mAcquireTime;
24183
24184 public SleepTokenImpl(String tag) {
24185 mTag = tag;
24186 mAcquireTime = SystemClock.uptimeMillis();
24187 }
24188
24189 @Override
24190 public void release() {
24191 synchronized (ActivityManagerService.this) {
24192 if (mSleepTokens.remove(this)) {
24193 updateSleepIfNeededLocked();
24194 }
24195 }
24196 }
24197
24198 @Override
24199 public String toString() {
24200 return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
24201 }
24202 }

app task实现类

 24204    /**
24205 * An implementation of IAppTask, that allows an app to manage its own tasks via
24206 * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
24207 * only the process that calls getAppTasks() can call the AppTask methods.
24208 */
24209 class AppTaskImpl extends IAppTask.Stub {
24210 private int mTaskId;
24211 private int mCallingUid;
24212
24213 public AppTaskImpl(int taskId, int callingUid) {
24214 mTaskId = taskId;
24215 mCallingUid = callingUid;
24216 }
24217
24218 private void checkCaller() {
24219 if (mCallingUid != Binder.getCallingUid()) {
24220 throw new SecurityException("Caller " + mCallingUid
24221 + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
24222 }
24223 }
24224
24225 @Override
24226 public void finishAndRemoveTask() {
24227 checkCaller();
24228
24229 synchronized (ActivityManagerService.this) {
24230 long origId = Binder.clearCallingIdentity();
24231 try {
24232 // We remove the task from recents to preserve backwards
24233 if (!mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
24234 REMOVE_FROM_RECENTS)) {
24235 throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
24236 }
24237 } finally {
24238 Binder.restoreCallingIdentity(origId);
24239 }
24240 }
24241 }
24242
24243 @Override
24244 public ActivityManager.RecentTaskInfo getTaskInfo() {
24245 checkCaller();
24246
24247 synchronized (ActivityManagerService.this) {
24248 long origId = Binder.clearCallingIdentity();
24249 try {
24250 TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
24251 if (tr == null) {
24252 throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
24253 }
24254 return createRecentTaskInfoFromTaskRecord(tr);
24255 } finally {
24256 Binder.restoreCallingIdentity(origId);
24257 }
24258 }
24259 }
24260
24261 @Override
24262 public void moveToFront() {
24263 checkCaller();
24264 // Will bring task to front if it already has a root activity.
24265 final long origId = Binder.clearCallingIdentity();
24266 try {
24267 synchronized (this) {
24268 mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
24269 }
24270 } finally {
24271 Binder.restoreCallingIdentity(origId);
24272 }
24273 }
24274
24275 @Override
24276 public int startActivity(IBinder whoThread, String callingPackage,
24277 Intent intent, String resolvedType, Bundle bOptions) {
24278 checkCaller();
24279
24280 int callingUser = UserHandle.getCallingUserId();
24281 TaskRecord tr;
24282 IApplicationThread appThread;
24283 synchronized (ActivityManagerService.this) {
24284 tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
24285 if (tr == null) {
24286 throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
24287 }
24288 appThread = IApplicationThread.Stub.asInterface(whoThread);
24289 if (appThread == null) {
24290 throw new IllegalArgumentException("Bad app thread " + appThread);
24291 }
24292 }
24293 return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
24294 resolvedType, null, null, null, null, 0, 0, null, null,
24295 null, bOptions, false, callingUser, null, tr, "AppTaskImpl");
24296 }
24297
24298 @Override
24299 public void setExcludeFromRecents(boolean exclude) {
24300 checkCaller();
24301
24302 synchronized (ActivityManagerService.this) {
24303 long origId = Binder.clearCallingIdentity();
24304 try {
24305 TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
24306 if (tr == null) {
24307 throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
24308 }
24309 Intent intent = tr.getBaseIntent();
24310 if (exclude) {
24311 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
24312 } else {
24313 intent.setFlags(intent.getFlags()
24314 & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
24315 }
24316 } finally {
24317 Binder.restoreCallingIdentity(origId);
24318 }
24319 }
24320 }
24321 }

杀掉包依赖关系

 24323    /**
24324 * Kill processes for the user with id userId and that depend on the package named packageName
24325 */
24326 @Override
24327 public void killPackageDependents(String packageName, int userId) {
24328 enforceCallingPermission(android.Manifest.permission.KILL_UID, "killPackageDependents()");
24329 if (packageName == null) {
24330 throw new NullPointerException(
24331 "Cannot kill the dependents of a package without its name.");
24332 }
24333
24334 long callingId = Binder.clearCallingIdentity();
24335 IPackageManager pm = AppGlobals.getPackageManager();
24336 int pkgUid = -1;
24337 try {
24338 pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
24339 } catch (RemoteException e) {
24340 }
24341 if (userId != UserHandle.USER_ALL && pkgUid == -1) {
24342 throw new IllegalArgumentException(
24343 "Cannot kill dependents of non-existing package " + packageName);
24344 }
24345 try {
24346 synchronized(this) {
24347 killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid), userId,
24348 ProcessList.FOREGROUND_APP_ADJ, false, true, true, false,
24349 "dep: " + packageName);
24350 }
24351 } finally {
24352 Binder.restoreCallingIdentity(callingId);
24353 }
24354 }

取消锁屏

 24356    @Override
24357 public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback)
24358 throws RemoteException {
24359 final long callingId = Binder.clearCallingIdentity();
24360 try {
24361 mKeyguardController.dismissKeyguard(token, callback);
24362 } finally {
24363 Binder.restoreCallingIdentity(callingId);
24364 }
24365 }

后台重启用户

 24367    @Override
24368 public int restartUserInBackground(final int userId) {
24369 return mUserController.restartUser(userId, /* foreground */ false);
24370 }
24371

调度、更新app info

 24372    @Override
24373 public void scheduleApplicationInfoChanged(List<String> packageNames, int userId) {
24374 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
24375 "scheduleApplicationInfoChanged()");
24376
24377 synchronized (this) {
24378 final long origId = Binder.clearCallingIdentity();
24379 try {
24380 updateApplicationInfoLocked(packageNames, userId);
24381 } finally {
24382 Binder.restoreCallingIdentity(origId);
24383 }
24384 }
24385 }
24386
24387 void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
24388 final boolean updateFrameworkRes = packagesToUpdate.contains("android");
24389 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
24390 final ProcessRecord app = mLruProcesses.get(i);
24391 if (app.thread == null) {
24392 continue;
24393 }
24394
24395 if (userId != UserHandle.USER_ALL && app.userId != userId) {
24396 continue;
24397 }
24398
24399 final int packageCount = app.pkgList.size();
24400 for (int j = 0; j < packageCount; j++) {
24401 final String packageName = app.pkgList.keyAt(j);
24402 if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
24403 try {
24404 final ApplicationInfo ai = AppGlobals.getPackageManager()
24405 .getApplicationInfo(packageName, 0 /*flags*/, app.userId);
24406 if (ai != null) {
24407 app.thread.scheduleApplicationInfoChanged(ai);
24408 }
24409 } catch (RemoteException e) {
24410 Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",
24411 packageName, app));
24412 }
24413 }
24414 }
24415 }
24416 }

附加到agent上

 24418    /**
24419 * Attach an agent to the specified process (proces name or PID)
24420 */
24421 public void attachAgent(String process, String path) {
24422 try {
24423 synchronized (this) {
24424 ProcessRecord proc = findProcessLocked(process, UserHandle.USER_SYSTEM, "attachAgent");
24425 if (proc == null || proc.thread == null) {
24426 throw new IllegalArgumentException("Unknown process: " + process);
24427 }
24428
24429 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
24430 if (!isDebuggable) {
24431 if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
24432 throw new SecurityException("Process not debuggable: " + proc);
24433 }
24434 }
24435
24436 proc.thread.attachAgent(path);
24437 }
24438 } catch (RemoteException e) {
24439 throw new IllegalStateException("Process disappeared");
24440 }
24441 }

Injector内部类

 24443    @VisibleForTesting
24444 public static class Injector {
24445 private NetworkManagementInternal mNmi;
24446
24447 public Context getContext() {
24448 return null;
24449 }
24450
24451 public AppOpsService getAppOpsService(File file, Handler handler) {
24452 return new AppOpsService(file, handler);
24453 }
24454
24455 public Handler getUiHandler(ActivityManagerService service) {
24456 return service.new UiHandler();
24457 }
24458
24459 public boolean isNetworkRestrictedForUid(int uid) {
24460 if (ensureHasNetworkManagementInternal()) {
24461 return mNmi.isNetworkRestrictedForUid(uid);
24462 }
24463 return false;
24464 }
24465
24466 private boolean ensureHasNetworkManagementInternal() {
24467 if (mNmi == null) {
24468 mNmi = LocalServices.getService(NetworkManagementInternal.class);
24469 }
24470 return mNmi != null;
24471 }
24472 }
24473}
24474

最新文章

  1. MySQL性能优化:索引
  2. 利用 ipset 封禁大量 IP
  3. Machine Learning in Action -- Logistic regression
  4. 【转】ROC和AUC介绍以及如何计算AUC
  5. Linux磁盘系统基础知识(转载)
  6. 【LeetCode】38 - Count and Say
  7. (三)Qt语言国际化
  8. 面试题_48_to_65_Java 集合框架的面试题
  9. logstahs 匹配isslog
  10. 关于LZO和LZOP
  11. Ionic2系列——在Ionic2中使用高德地图
  12. html+css底部自动固定底部
  13. Google会思考的深度学习系统
  14. genymotion的安装及运行
  15. hibernate框架(1)---Hibernate增删改查
  16. js中parseInt和Number
  17. 【洛谷p2822】组合数问题
  18. 算法笔记_219:泊松分酒(Java)
  19. request.getParameterMap()获得Map中的数据
  20. hdoj 4445 Crazy Tank 物理题/枚举角度1

热门文章

  1. Cookie和Session的区别和联系
  2. p5471 [NOI2019]弹跳
  3. CAS 认证
  4. ubuntu更换源
  5. Unity shader with lightmap
  6. 编程语言 - PHP
  7. [LeetCode] 4. Median of Two Sorted Arrays(想法题/求第k小的数)
  8. Learning OSG programing---Multi Camera in Multi window 在多窗口中创建多相机
  9. Java 遍历某个目录
  10. 从0 开始手写一个 RPC 框架,轻松搞定!