summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/content/src/com/android/commands/content/Content.java2
-rw-r--r--cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java2
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/com/android/internal/app/procstats/AssociationState.java233
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessState.java6
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessStats.java123
-rw-r--r--core/java/com/android/internal/app/procstats/ServiceState.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java62
-rw-r--r--services/core/java/com/android/server/am/ConnectionRecord.java13
-rw-r--r--services/core/java/com/android/server/am/ContentProviderConnection.java13
-rw-r--r--services/core/java/com/android/server/am/ContentProviderRecord.java67
-rw-r--r--services/core/java/com/android/server/am/ProcessStatsService.java6
12 files changed, 445 insertions, 86 deletions
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 6e0bd3a81d84..36e51b9703c9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -462,7 +462,7 @@ public class Content {
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- providerName, mUserId, token);
+ providerName, mUserId, token, "*cmd*");
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 653851546d01..950a258d123d 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -62,7 +62,7 @@ public class ShellUiAutomatorBridge extends UiAutomatorBridge {
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- providerName, UserHandle.USER_SYSTEM, token);
+ providerName, UserHandle.USER_SYSTEM, token, "*uiautomator*");
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f9c39165b2c8..19d7c83818f6 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -268,7 +268,7 @@ interface IActivityManager {
void showBootMessage(in CharSequence msg, boolean always);
void killAllBackgroundProcesses();
ContentProviderHolder getContentProviderExternal(in String name, int userId,
- in IBinder token);
+ in IBinder token, String tag);
void removeContentProviderExternal(in String name, in IBinder token);
// Get memory information about the calling process.
void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index e73ec1c40d19..e5d6556e1218 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -21,37 +21,143 @@ import android.os.Parcel;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.Slog;
import android.util.TimeUtils;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Objects;
public final class AssociationState {
private static final String TAG = "ProcessStats";
private static final boolean DEBUG = false;
- private final String mPackage;
+ private final ProcessStats mProcessStats;
+ private final ProcessStats.PackageState mPackageState;
private final String mProcessName;
private final String mName;
private final DurationsTable mDurations;
public final class SourceState {
+ final SourceKey mKey;
+ int mProcStateSeq = -1;
+ int mProcState = ProcessStats.STATE_NOTHING;
+ boolean mInTrackingList;
+ int mNesting;
+ int mCount;
+ long mStartUptime;
+ long mDuration;
+ long mTrackingUptime;
+ int mActiveCount;
+ long mActiveStartUptime;
+ long mActiveDuration;
+
+ SourceState(SourceKey key) {
+ mKey = key;
+ }
+
+ public AssociationState getAssociationState() {
+ return AssociationState.this;
+ }
+
+ public String getProcessName() {
+ return mKey.mProcess;
+ }
+
+ public int getUid() {
+ return mKey.mUid;
+ }
+
+ public void trackProcState(int procState, int seq, long now) {
+ procState = ProcessState.PROCESS_STATE_TO_STATE[procState];
+ if (seq != mProcStateSeq) {
+ mProcStateSeq = seq;
+ mProcState = procState;
+ } else if (procState < mProcState) {
+ mProcState = procState;
+ }
+ if (procState < ProcessStats.STATE_HOME) {
+ if (!mInTrackingList) {
+ mInTrackingList = true;
+ mTrackingUptime = now;
+ mProcessStats.mTrackingAssociations.add(this);
+ }
+ } else {
+ stopTracking(now);
+ }
+ }
+
public void stop() {
mNesting--;
if (mNesting == 0) {
- mDuration += SystemClock.uptimeMillis() - mStartTime;
+ mDuration += SystemClock.uptimeMillis() - mStartUptime;
mNumActive--;
+ stopTracking(SystemClock.uptimeMillis());
}
}
- int mNesting;
- int mCount;
- long mStartTime;
- long mDuration;
+ void startActive(long now) {
+ if (mInTrackingList) {
+ if (mActiveStartUptime == 0) {
+ mActiveStartUptime = now;
+ mActiveCount++;
+ }
+ } else {
+ Slog.wtf(TAG, "startActive while not tracking: " + this);
+ }
+ }
+
+ void stopActive(long now) {
+ if (mActiveStartUptime != 0) {
+ if (!mInTrackingList) {
+ Slog.wtf(TAG, "stopActive while not tracking: " + this);
+ }
+ mActiveDuration += now - mActiveStartUptime;
+ mActiveStartUptime = 0;
+ }
+ }
+
+ void stopTracking(long now) {
+ stopActive(now);
+ if (mInTrackingList) {
+ mInTrackingList = false;
+ // Do a manual search for where to remove, since these objects will typically
+ // be towards the end of the array.
+ final ArrayList<SourceState> list = mProcessStats.mTrackingAssociations;
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == this) {
+ list.remove(i);
+ return;
+ }
+ }
+ Slog.wtf(TAG, "Stop tracking didn't find in tracking list: " + this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append("SourceState{").append(Integer.toHexString(System.identityHashCode(this)))
+ .append(" ").append(mKey.mProcess).append("/").append(mKey.mUid);
+ if (mProcState != ProcessStats.STATE_NOTHING) {
+ sb.append(" ").append(DumpUtils.STATE_NAMES[mProcState]).append(" #")
+ .append(mProcStateSeq);
+ }
+ sb.append("}");
+ return sb.toString();
+ }
}
- final static class SourceKey {
+ private final static class SourceKey {
+ /**
+ * UID, consider this final. Not final just to avoid a temporary object during lookup.
+ */
int mUid;
+
+ /**
+ * Process name, consider this final. Not final just to avoid a temporary object during
+ * lookup.
+ */
String mProcess;
SourceKey(int uid, String process) {
@@ -82,7 +188,6 @@ public final class AssociationState {
sb.append('}');
return sb.toString();
}
-
}
/**
@@ -92,18 +197,26 @@ public final class AssociationState {
private final SourceKey mTmpSourceKey = new SourceKey(0, null);
+ private ProcessState mProc;
+
private int mNumActive;
- public AssociationState(ProcessStats processStats, String pkg, String name,
- String processName) {
- mPackage = pkg;
+ public AssociationState(ProcessStats processStats, ProcessStats.PackageState packageState,
+ String name, String processName, ProcessState proc) {
+ mProcessStats = processStats;
+ mPackageState = packageState;
mName = name;
mProcessName = processName;
mDurations = new DurationsTable(processStats.mTableData);
+ mProc = proc;
+ }
+
+ public int getUid() {
+ return mPackageState.mUid;
}
public String getPackage() {
- return mPackage;
+ return mPackageState.mPackageName;
}
public String getProcessName() {
@@ -114,18 +227,27 @@ public final class AssociationState {
return mName;
}
+ public ProcessState getProcess() {
+ return mProc;
+ }
+
+ public void setProcess(ProcessState proc) {
+ mProc = proc;
+ }
+
public SourceState startSource(int uid, String processName) {
mTmpSourceKey.mUid = uid;
mTmpSourceKey.mProcess = processName;
SourceState src = mSources.get(mTmpSourceKey);
if (src == null) {
- src = new SourceState();
- mSources.put(new SourceKey(uid, processName), src);
+ SourceKey key = new SourceKey(uid, processName);
+ src = new SourceState(key);
+ mSources.put(key, src);
}
src.mNesting++;
if (src.mNesting == 1) {
src.mCount++;
- src.mStartTime = SystemClock.uptimeMillis();
+ src.mStartUptime = SystemClock.uptimeMillis();
mNumActive++;
}
return src;
@@ -138,11 +260,13 @@ public final class AssociationState {
final SourceState otherSrc = other.mSources.valueAt(isrc);
SourceState mySrc = mSources.get(key);
if (mySrc == null) {
- mySrc = new SourceState();
+ mySrc = new SourceState(key);
mSources.put(key, mySrc);
}
mySrc.mCount += otherSrc.mCount;
mySrc.mDuration += otherSrc.mDuration;
+ mySrc.mActiveCount += otherSrc.mActiveCount;
+ mySrc.mActiveDuration += otherSrc.mActiveDuration;
}
}
@@ -160,8 +284,15 @@ public final class AssociationState {
SourceState src = mSources.valueAt(isrc);
if (src.mNesting > 0) {
src.mCount = 1;
- src.mStartTime = now;
+ src.mStartUptime = now;
src.mDuration = 0;
+ if (src.mActiveStartUptime > 0) {
+ src.mActiveCount = 1;
+ src.mActiveStartUptime = now;
+ } else {
+ src.mActiveCount = 0;
+ }
+ src.mActiveDuration = 0;
} else {
mSources.removeAt(isrc);
}
@@ -169,7 +300,7 @@ public final class AssociationState {
}
}
- public void writeToParcel(ProcessStats stats, Parcel out, long now) {
+ public void writeToParcel(ProcessStats stats, Parcel out, long nowUptime) {
mDurations.writeToParcel(out);
final int NSRC = mSources.size();
out.writeInt(NSRC);
@@ -180,9 +311,15 @@ public final class AssociationState {
stats.writeCommonString(out, key.mProcess);
out.writeInt(src.mCount);
out.writeLong(src.mDuration);
+ out.writeInt(src.mActiveCount);
+ out.writeLong(src.mActiveDuration);
}
}
+ /**
+ * Returns non-null if all else fine, else a String that describes the error that
+ * caused it to fail.
+ */
public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) {
if (!mDurations.readFromParcel(in)) {
return "Duration table corrupt";
@@ -195,21 +332,27 @@ public final class AssociationState {
final int uid = in.readInt();
final String procName = stats.readCommonString(in, parcelVersion);
final SourceKey key = new SourceKey(uid, procName);
- final SourceState src = new SourceState();
+ final SourceState src = new SourceState(key);
src.mCount = in.readInt();
src.mDuration = in.readLong();
+ src.mActiveCount = in.readInt();
+ src.mActiveDuration = in.readLong();
mSources.put(key, src);
}
return null;
}
- public void commitStateTime(long now) {
+ public void commitStateTime(long nowUptime) {
if (isInUse()) {
for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
SourceState src = mSources.valueAt(isrc);
if (src.mNesting > 0) {
- src.mDuration += now - src.mStartTime;
- src.mStartTime = now;
+ src.mDuration += nowUptime - src.mStartUptime;
+ src.mStartUptime = nowUptime;
+ }
+ if (src.mActiveStartUptime > 0) {
+ src.mActiveDuration += nowUptime - src.mActiveStartUptime;
+ src.mActiveStartUptime = nowUptime;
}
}
}
@@ -237,7 +380,7 @@ public final class AssociationState {
pw.print(src.mCount);
long duration = src.mDuration;
if (src.mNesting > 0) {
- duration += now - src.mStartTime;
+ duration += now - src.mStartUptime;
}
if (dumpAll) {
pw.print(" / Duration ");
@@ -248,9 +391,37 @@ public final class AssociationState {
}
DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
if (src.mNesting > 0) {
- pw.print(" (running)");
+ pw.print(" (running");
+ if (src.mProcState != ProcessStats.STATE_NOTHING) {
+ pw.print(" / ");
+ pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+ pw.print(" #");
+ pw.print(src.mProcStateSeq);
+ }
+ pw.print(")");
}
pw.println();
+ if (src.mActiveCount > 0) {
+ pw.print(prefixInner);
+ pw.print(" Active count ");
+ pw.print(src.mActiveCount);
+ duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
+ }
+ if (dumpAll) {
+ pw.print(" / Duration ");
+ TimeUtils.formatDuration(duration, pw);
+ pw.print(" / ");
+ } else {
+ pw.print(" / time ");
+ }
+ DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+ if (src.mActiveStartUptime > 0) {
+ pw.print(" (running)");
+ }
+ pw.println();
+ }
}
}
@@ -277,7 +448,15 @@ public final class AssociationState {
pw.print(src.mCount);
long duration = src.mDuration;
if (src.mNesting > 0) {
- duration += now - src.mStartTime;
+ duration += now - src.mStartUptime;
+ }
+ pw.print(",");
+ pw.print(duration);
+ pw.print(",");
+ pw.print(src.mActiveCount);
+ duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
}
pw.print(",");
pw.print(duration);
@@ -287,7 +466,7 @@ public final class AssociationState {
public String toString() {
return "AssociationState{" + Integer.toHexString(System.identityHashCode(this))
- + " " + mName + " pkg=" + mPackage + " proc="
- + Integer.toHexString(System.identityHashCode(this)) + "}";
+ + " " + mName + " pkg=" + mPackageState.mPackageName + " proc="
+ + Integer.toHexString(System.identityHashCode(mProc)) + "}";
}
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 5a08f62f218b..dbf7c93dadd2 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -71,7 +71,7 @@ public final class ProcessState {
private static final boolean DEBUG_PARCEL = false;
// Map from process states to the states we track.
- private static final int[] PROCESS_STATE_TO_STATE = new int[] {
+ static final int[] PROCESS_STATE_TO_STATE = new int[] {
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
@@ -378,6 +378,10 @@ public final class ProcessState {
}
}
+ public int getState() {
+ return mCurState;
+ }
+
public void commitStateTime(long now) {
if (mCurState != STATE_NOTHING) {
long dur = now - mStartTime;
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 1f871d9f92b8..3cafa5e5ec20 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -16,6 +16,7 @@
package com.android.internal.app.procstats;
+import android.content.ComponentName;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcelable;
@@ -157,7 +158,7 @@ public final class ProcessStats implements Parcelable {
};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 31;
+ private static final int PARCEL_VERSION = 32;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -168,6 +169,8 @@ public final class ProcessStats implements Parcelable {
public final ProcessMap<LongSparseArray<PackageState>> mPackages = new ProcessMap<>();
public final ProcessMap<ProcessState> mProcesses = new ProcessMap<>();
+ public final ArrayList<AssociationState.SourceState> mTrackingAssociations = new ArrayList<>();
+
public final long[] mMemFactorDurations = new long[ADJ_COUNT];
public int mMemFactor = STATE_NOTHING;
public long mStartTime;
@@ -1203,8 +1206,8 @@ public final class ProcessStats implements Parcelable {
AssociationState asc = hadData
? pkgState.mAssociations.get(associationName) : null;
if (asc == null) {
- asc = new AssociationState(this, pkgName, associationName,
- processName);
+ asc = new AssociationState(this, pkgState, associationName,
+ processName, null);
}
String errorMsg = asc.readFromParcel(this, in, version);
if (errorMsg != null) {
@@ -1308,6 +1311,17 @@ public final class ProcessStats implements Parcelable {
Slog.d(TAG, "GETPROC leaving proc of " + ss);
}
}
+ // Also update active associations.
+ for (int i=commonPkgState.mAssociations.size()-1; i>=0; i--) {
+ AssociationState as = commonPkgState.mAssociations.valueAt(i);
+ if (as.getProcess() == commonProc) {
+ if (DEBUG) Slog.d(TAG, "GETPROC switching association to cloned: "
+ + as);
+ as.setProcess(cloned);
+ } else if (DEBUG) {
+ Slog.d(TAG, "GETPROC leaving proc of " + as);
+ }
+ }
} else {
Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage()
+ "/" + pkgState.mUid + " for proc " + commonProc.getName());
@@ -1356,12 +1370,41 @@ public final class ProcessStats implements Parcelable {
}
final ProcessState procs = processName != null
? getProcessStateLocked(packageName, uid, vers, processName) : null;
- as = new AssociationState(this, packageName, className, processName);
+ as = new AssociationState(this, pkgs, className, processName, procs);
pkgs.mAssociations.put(className, as);
if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + procs);
return as;
}
+ public void updateTrackingAssociationsLocked(int curSeq, long now) {
+ final int NUM = mTrackingAssociations.size();
+ for (int i = NUM - 1; i >= 0; i--) {
+ final AssociationState.SourceState act = mTrackingAssociations.get(i);
+ if (act.mProcStateSeq != curSeq) {
+ act.mInTrackingList = false;
+ act.mProcState = STATE_NOTHING;
+ mTrackingAssociations.remove(i);
+ } else {
+ final ProcessState proc = act.getAssociationState().getProcess();
+ if (proc != null) {
+ if (act.mProcState == proc.getState()) {
+ act.startActive(now);
+ } else {
+ act.stopActive(now);
+ if (act.mProcState < proc.getState()) {
+ Slog.w(TAG, "Tracking association " + act + " whose proc state "
+ + act.mProcState + " is better than process " + proc
+ + " proc state " + proc.getState());
+ }
+ }
+ } else {
+ Slog.wtf(TAG, "Tracking association without process: " + act
+ + " in " + act.getAssociationState());
+ }
+ }
+ }
+ }
+
public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
boolean dumpAll, boolean activeOnly) {
long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
@@ -1543,10 +1586,70 @@ public final class ProcessStats implements Parcelable {
proc.dumpInternalLocked(pw, " ", dumpAll);
}
}
+
if (dumpAll) {
- pw.println();
+ if (sepNeeded) {
+ pw.println();
+ }
+ sepNeeded = true;
pw.print(" Total procs: "); pw.print(numShownProcs);
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
+ if (mTrackingAssociations.size() > 0) {
+ pw.println();
+ pw.println("Tracking associations:");
+ for (int i = 0; i < mTrackingAssociations.size(); i++) {
+ final AssociationState.SourceState src = mTrackingAssociations.get(i);
+ final AssociationState asc = src.getAssociationState();
+ pw.print(" #");
+ pw.print(i);
+ pw.print(": ");
+ pw.print(asc.getProcessName());
+ pw.print("/");
+ UserHandle.formatUid(pw, asc.getUid());
+ pw.print(" <- ");
+ pw.print(src.getProcessName());
+ pw.print("/");
+ UserHandle.formatUid(pw, src.getUid());
+ pw.println(":");
+ pw.print(" Tracking for: ");
+ TimeUtils.formatDuration(now - src.mTrackingUptime, pw);
+ pw.println();
+ pw.print(" Component: ");
+ pw.print(new ComponentName(asc.getPackage(), asc.getName())
+ .flattenToShortString());
+ pw.println();
+ pw.print(" Proc state: ");
+ if (src.mProcState != ProcessStats.STATE_NOTHING) {
+ pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+ } else {
+ pw.print("--");
+ }
+ pw.print(" #");
+ pw.println(src.mProcStateSeq);
+ pw.print(" Process: ");
+ pw.println(asc.getProcess());
+ if (src.mActiveCount > 0) {
+ pw.print(" Active count ");
+ pw.print(src.mActiveCount);
+ long duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
+ }
+ if (dumpAll) {
+ pw.print(" / Duration ");
+ TimeUtils.formatDuration(duration, pw);
+ pw.print(" / ");
+ } else {
+ pw.print(" / time ");
+ }
+ DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+ if (src.mActiveStartUptime > 0) {
+ pw.print(" (running)");
+ }
+ pw.println();
+ }
+ }
+ }
}
if (sepNeeded) {
@@ -1985,15 +2088,19 @@ public final class ProcessStats implements Parcelable {
mVersionCode = versionCode;
}
- public AssociationState getAssociationStateLocked(String processName, String className) {
+ public AssociationState getAssociationStateLocked(ProcessState proc, String className) {
AssociationState as = mAssociations.get(className);
if (as != null) {
if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
+ if (proc != null) {
+ as.setProcess(proc);
+ }
return as;
}
- as = new AssociationState(mProcessStats, mPackageName, className, processName);
+ as = new AssociationState(mProcessStats, this, className, proc.getName(),
+ proc);
mAssociations.put(className, as);
- if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + processName);
+ if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + proc.getName());
return as;
}
}
diff --git a/core/java/com/android/internal/app/procstats/ServiceState.java b/core/java/com/android/internal/app/procstats/ServiceState.java
index 53ed5c0128d8..04e61e067f53 100644
--- a/core/java/com/android/internal/app/procstats/ServiceState.java
+++ b/core/java/com/android/internal/app/procstats/ServiceState.java
@@ -554,6 +554,6 @@ public final class ServiceState {
public String toString() {
return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
+ " " + mName + " pkg=" + mPackage + " proc="
- + Integer.toHexString(System.identityHashCode(this)) + "}";
+ + Integer.toHexString(System.identityHashCode(mProc)) + "}";
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5028fd59124f..a23060982547 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -86,7 +86,6 @@ import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
import static android.os.Process.startWebView;
import static android.os.Process.zygoteProcess;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
@@ -164,7 +163,6 @@ import android.app.ActivityManagerInternal;
import android.app.ActivityManagerProto;
import android.app.ActivityOptions;
import android.app.ActivityThread;
-import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
@@ -206,7 +204,6 @@ import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -262,7 +259,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.Process;
@@ -285,7 +281,6 @@ import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.provider.Downloads;
import android.provider.Settings;
-import android.service.voice.IVoiceInteractionSession;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.SuggestionSpan;
@@ -323,10 +318,8 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.SystemUserHomeActivity;
-import com.android.internal.app.procstats.AssociationState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -364,21 +357,9 @@ import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
-import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
-import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
-import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
-import com.android.server.am.ActivityManagerServiceDumpServicesProto;
-import com.android.server.am.ActivityManagerServiceProto;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.GrantUriProto;
-import com.android.server.am.ImportanceTokenProto;
-import com.android.server.am.MemInfoDumpProto;
import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.am.NeededUriGrantsProto;
-import com.android.server.am.ProcessOomProto;
-import com.android.server.am.ProcessToGcProto;
-import com.android.server.am.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -387,7 +368,6 @@ import com.android.server.pm.dex.DexManager;
import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
@@ -9020,7 +9000,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
ContentProviderConnection incProviderCountLocked(ProcessRecord r,
- final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
+ final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
+ String callingTag, boolean stable) {
if (r != null) {
for (int i=0; i<r.conProviders.size(); i++) {
ContentProviderConnection conn = r.conProviders.get(i);
@@ -9055,7 +9036,7 @@ public class ActivityManagerService extends IActivityManager.Stub
cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
return conn;
}
- cpr.addExternalProcessHandleLocked(externalProcessToken);
+ cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
return null;
}
@@ -9132,7 +9113,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
- String name, IBinder token, boolean stable, int userId) {
+ String name, IBinder token, int callingUid, String callingTag, boolean stable,
+ int userId) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
@@ -9225,7 +9207,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// In this case the provider instance already exists, so we can
// return it right away.
- conn = incProviderCountLocked(r, cpr, token, stable);
+ conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
// If this is a perceptible app accessing the provider,
@@ -9469,7 +9451,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mProviderMap.putProviderByName(name, cpr);
- conn = incProviderCountLocked(r, cpr, token, stable);
+ conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
if (conn != null) {
conn.waiting = true;
}
@@ -9580,21 +9562,23 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
// with cross-user grant.
- return getContentProviderImpl(caller, name, null, stable, userId);
+ return getContentProviderImpl(caller, name, null, Binder.getCallingUid(), null, stable,
+ userId);
}
public ContentProviderHolder getContentProviderExternal(
- String name, int userId, IBinder token) {
+ String name, int userId, IBinder token, String tag) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "getContentProvider", null);
- return getContentProviderExternalUnchecked(name, token, userId);
+ return getContentProviderExternalUnchecked(name, token, Binder.getCallingUid(),
+ tag != null ? tag : "*external*", userId);
}
private ContentProviderHolder getContentProviderExternalUnchecked(String name,
- IBinder token, int userId) {
- return getContentProviderImpl(null, name, token, true, userId);
+ IBinder token, int callingUid, String callingTag, int userId) {
+ return getContentProviderImpl(null, name, token, callingUid, callingTag, true, userId);
}
/**
@@ -9986,7 +9970,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
ContentProviderHolder holder = null;
try {
- holder = getContentProviderExternalUnchecked(name, null, userId);
+ holder = getContentProviderExternalUnchecked(name, null, callingUid,
+ "*getmimetype*", userId);
if (holder != null) {
return holder.provider.getType(uri);
}
@@ -10201,7 +10186,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final int userId = UserHandle.getCallingUserId();
final Uri uri = Uri.parse(uriString);
String name = uri.getAuthority();
- ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
+ ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null,
+ Binder.getCallingUid(), "*opencontent*", userId);
ParcelFileDescriptor pfd = null;
if (cph != null) {
// We record the binder invoker's uid in thread-local storage before
@@ -19281,10 +19267,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// all connected clients.
ConnectionRecord cr = clist.get(i);
if (cr.binding.client == app) {
- // Binding to ourself is not interesting.
+ // Binding to oneself is not interesting.
continue;
}
+ boolean trackedProcState = false;
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
@@ -19356,6 +19343,8 @@ public class ActivityManagerService extends IActivityManager.Stub
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
+ cr.trackProcState(procState, mAdjSeq, now);
+ trackedProcState = true;
}
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
@@ -19441,6 +19430,9 @@ public class ActivityManagerService extends IActivityManager.Stub
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
}
}
+ if (!trackedProcState) {
+ cr.trackProcState(clientProcState, mAdjSeq, now);
+ }
if (procState > clientProcState) {
procState = clientProcState;
if (adjType == null) {
@@ -19570,6 +19562,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
+ conn.trackProcState(clientProcState, mAdjSeq, now);
if (procState > clientProcState) {
procState = clientProcState;
}
@@ -20839,6 +20832,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
+
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
@@ -20902,6 +20896,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+
incrementProcStateSeqAndNotifyAppsLocked();
mNumServiceProcs = mNewNumServiceProcs;
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index c348aeee8b86..2cea4faba613 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -106,7 +106,10 @@ final class ConnectionRecord {
}
public void startAssociationIfNeeded() {
- if (association == null) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (association == null && (binding.service.appInfo.uid != clientUid
+ || !binding.service.processName.equals(clientProcessName))) {
ProcessStats.ProcessStateHolder holder = binding.service.app != null
? binding.service.app.pkgList.get(binding.service.name.getPackageName()) : null;
if (holder == null) {
@@ -116,7 +119,7 @@ final class ConnectionRecord {
Slog.wtf(TAG_AM, "Inactive holder in referenced service "
+ binding.service.name.toShortString() + ": proc=" + binding.service.app);
} else {
- association = holder.pkg.getAssociationStateLocked(binding.service.processName,
+ association = holder.pkg.getAssociationStateLocked(holder.state,
binding.service.name.getClassName()).startSource(clientUid,
clientProcessName);
@@ -124,6 +127,12 @@ final class ConnectionRecord {
}
}
+ public void trackProcState(int procState, int seq, long now) {
+ if (association != null) {
+ association.trackProcState(procState, seq, now);
+ }
+ }
+
public void stopAssociation() {
if (association != null) {
association.stop();
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index 0320b10b9a7a..36d3f4f619de 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -53,7 +53,10 @@ public final class ContentProviderConnection extends Binder {
}
public void startAssociationIfNeeded() {
- if (association == null) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (association == null && (provider.appInfo.uid != client.uid
+ || !provider.info.processName.equals(client.processName))) {
ProcessStats.ProcessStateHolder holder = provider.proc != null
? provider.proc.pkgList.get(provider.name.getPackageName()) : null;
if (holder == null) {
@@ -63,13 +66,19 @@ public final class ContentProviderConnection extends Binder {
Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ provider.name.toShortString() + ": proc=" + provider.proc);
} else {
- association = holder.pkg.getAssociationStateLocked(provider.info.processName,
+ association = holder.pkg.getAssociationStateLocked(holder.state,
provider.name.getClassName()).startSource(client.uid, client.processName);
}
}
}
+ public void trackProcState(int procState, int seq, long now) {
+ if (association != null) {
+ association.trackProcState(procState, seq, now);
+ }
+ }
+
public void stopAssociation() {
if (association != null) {
association.stop();
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index 07ae1aedc686..53783bebe7f1 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
import android.app.ContentProviderHolder;
import android.content.ComponentName;
import android.content.IContentProvider;
@@ -26,11 +28,14 @@ import android.os.IBinder.DeathRecipient;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.app.procstats.AssociationState;
+import com.android.internal.app.procstats.ProcessStats;
+
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
final class ContentProviderRecord implements ComponentName.WithComponentName {
final ActivityManagerService service;
@@ -46,7 +51,7 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
= new ArrayList<ContentProviderConnection>();
//final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
// Handles for non-framework processes supported by this provider
- HashMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
+ ArrayMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
// Count for external process for which we have no handles.
int externalProcessNoHandleCount;
ProcessRecord proc; // if non-null, hosting process.
@@ -93,6 +98,16 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
conn.stopAssociation();
}
}
+ if (externalProcessTokenToHandle != null) {
+ for (int iext = externalProcessTokenToHandle.size() - 1; iext >= 0; iext--) {
+ final ExternalProcessHandle handle = externalProcessTokenToHandle.valueAt(iext);
+ if (proc != null) {
+ handle.startAssociationIfNeeded(this);
+ } else {
+ handle.stopAssociation();
+ }
+ }
+ }
}
public boolean canRunHere(ProcessRecord app) {
@@ -100,17 +115,18 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
&& uid == app.info.uid;
}
- public void addExternalProcessHandleLocked(IBinder token) {
+ public void addExternalProcessHandleLocked(IBinder token, int callingUid, String callingTag) {
if (token == null) {
externalProcessNoHandleCount++;
} else {
if (externalProcessTokenToHandle == null) {
- externalProcessTokenToHandle = new HashMap<IBinder, ExternalProcessHandle>();
+ externalProcessTokenToHandle = new ArrayMap<>();
}
ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
if (handle == null) {
- handle = new ExternalProcessHandle(token);
+ handle = new ExternalProcessHandle(token, callingUid, callingTag);
externalProcessTokenToHandle.put(token, handle);
+ handle.startAssociationIfNeeded(this);
}
handle.mAcquisitionCount++;
}
@@ -141,6 +157,7 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
private void removeExternalProcessHandleInternalLocked(IBinder token) {
ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
handle.unlinkFromOwnDeathLocked();
+ handle.stopAssociation();
externalProcessTokenToHandle.remove(token);
if (externalProcessTokenToHandle.size() == 0) {
externalProcessTokenToHandle = null;
@@ -246,11 +263,16 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
private class ExternalProcessHandle implements DeathRecipient {
private static final String LOG_TAG = "ExternalProcessHanldle";
- private final IBinder mToken;
- private int mAcquisitionCount;
+ final IBinder mToken;
+ final int mOwningUid;
+ final String mOwningProcessName;
+ int mAcquisitionCount;
+ AssociationState.SourceState mAssociation;
- public ExternalProcessHandle(IBinder token) {
+ public ExternalProcessHandle(IBinder token, int owningUid, String owningProcessName) {
mToken = token;
+ mOwningUid = owningUid;
+ mOwningProcessName = owningProcessName;
try {
token.linkToDeath(this, 0);
} catch (RemoteException re) {
@@ -262,6 +284,35 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
mToken.unlinkToDeath(this, 0);
}
+ public void startAssociationIfNeeded(ContentProviderRecord provider) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (mAssociation == null && (provider.appInfo.uid != mOwningUid
+ || !provider.info.processName.equals(mOwningProcessName))) {
+ ProcessStats.ProcessStateHolder holder = provider.proc != null
+ ? provider.proc.pkgList.get(provider.name.getPackageName()) : null;
+ if (holder == null) {
+ Slog.wtf(TAG_AM, "No package in referenced provider "
+ + provider.name.toShortString() + ": proc=" + provider.proc);
+ } else if (holder.pkg == null) {
+ Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ + provider.name.toShortString() + ": proc=" + provider.proc);
+ } else {
+ mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
+ provider.name.getClassName()).startSource(mOwningUid,
+ mOwningProcessName);
+
+ }
+ }
+ }
+
+ public void stopAssociation() {
+ if (mAssociation != null) {
+ mAssociation.stop();
+ mAssociation = null;
+ }
+ }
+
@Override
public void binderDied() {
synchronized (service) {
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index e1bc1bccdb14..f0bd8fa31478 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -32,7 +32,6 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.procstats.AssociationState;
import com.android.internal.app.procstats.DumpUtils;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessState;
@@ -194,6 +193,11 @@ public final class ProcessStatsService extends IProcessStats.Stub {
}
@GuardedBy("mAm")
+ public void updateTrackingAssociationsLocked(int curSeq, long now) {
+ mProcessStats.updateTrackingAssociationsLocked(curSeq, now);
+ }
+
+ @GuardedBy("mAm")
public boolean shouldWriteNowLocked(long now) {
if (now > (mLastWriteTime+WRITE_PERIOD)) {
if (SystemClock.elapsedRealtime()