summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2017-01-31 15:27:13 -0800
committerDianne Hackborn <hackbod@google.com>2017-02-03 16:07:54 -0800
commit340417356d92d0db71d0692344e66886ca795dfd (patch)
tree6e8ba6c955fc064c066d59ddc2275d3773b1b3c7 /core/java/android
parent7b6bcb6005c7e1d4b6ad1fec43e9e2dfad86663f (diff)
Implement issue #30977956: Enable Instrumentation tests for multi-process apps
New android:targetProcess attribute on <instrumentation> allows you to specify the processes the instrumentation will run in. This reworks how instrumentation is run in the activity manager to better formalize its state and semantics, allowing us to keep track of it across multiple processes. This also clearly defines what happens when multiple instrumentations are running at the same time, which is useful for writing CTS tests that test the instrumentation APIs themselves. Adds a couple new APIs to Instrumentation that helps with the new situation where instrumentation can run concurrently in multiple processes. Test: new CTS tests added (textXxxProcessInstrumentation in ActivityManagerTest.java in cts/tests/app/src) Change-Id: I2811e6c75bc98d4856045b2f0a45fb24af5d366f
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/IActivityManager.aidl1
-rw-r--r--core/java/android/app/Instrumentation.java30
-rw-r--r--core/java/android/content/pm/InstrumentationInfo.java10
-rw-r--r--core/java/android/content/pm/PackageParser.java5
4 files changed, 44 insertions, 2 deletions
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3cc6282d6ab3..99ae96df01eb 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -145,6 +145,7 @@ interface IActivityManager {
int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
in IUiAutomationConnection connection, int userId,
in String abiOverride);
+ void addInstrumentationResults(in IApplicationThread target, in Bundle results);
void finishInstrumentation(in IApplicationThread target, int resultCode,
in Bundle results);
/**
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index b1bdea1cb502..4db29fb5a72a 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -186,11 +186,25 @@ public class Instrumentation {
}
}
}
-
+
+ /**
+ * Report some results in the middle of instrumentation execution. Later results (including
+ * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
+ */
+ public void addResults(Bundle results) {
+ IActivityManager am = ActivityManager.getService();
+ try {
+ am.addInstrumentationResults(mThread.getApplicationThread(), results);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
/**
* Terminate instrumentation of the application. This will cause the
* application process to exit, removing this instrumentation from the next
- * time the application is started.
+ * time the application is started. If multiple processes are currently running
+ * for this instrumentation, all of those processes will be killed.
*
* @param resultCode Overall success/failure of instrumentation.
* @param results Any results to send back to the code that started the
@@ -278,6 +292,18 @@ public class Instrumentation {
}
/**
+ * Return the name of the process this instrumentation is running in. Note this should
+ * only be used for testing and debugging. If you are thinking about using this to,
+ * for example, conditionalize what is initialized in an Application class, it is strongly
+ * recommended to instead use lazy initialization (such as a getter for the state that
+ * only creates it when requested). This can greatly reduce the work your process does
+ * when created for secondary things, such as to receive a broadcast.
+ */
+ public String getProcessName() {
+ return mThread.getProcessName();
+ }
+
+ /**
* Check whether this instrumentation was started with profiling enabled.
*
* @return Returns true if profiling was enabled when starting, else false.
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index a135d8f11acd..59c530730170 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -34,6 +34,13 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
public String targetPackage;
/**
+ * Names of the process(es) this instrumentation will run in. If not specified, only
+ * runs in the main process of the targetPackage. Can either be a comma-separated list
+ * of process names or '*' for any process that launches to run targetPackage code.
+ */
+ public String targetProcess;
+
+ /**
* Full path to the base APK for this application.
*/
public String sourceDir;
@@ -113,6 +120,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
public InstrumentationInfo(InstrumentationInfo orig) {
super(orig);
targetPackage = orig.targetPackage;
+ targetProcess = orig.targetProcess;
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
splitNames = orig.splitNames;
@@ -141,6 +149,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
public void writeToParcel(Parcel dest, int parcelableFlags) {
super.writeToParcel(dest, parcelableFlags);
dest.writeString(targetPackage);
+ dest.writeString(targetProcess);
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
dest.writeStringArray(splitNames);
@@ -170,6 +179,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
private InstrumentationInfo(Parcel source) {
super(source);
targetPackage = source.readString();
+ targetProcess = source.readString();
sourceDir = source.readString();
publicSourceDir = source.readString();
splitNames = source.readStringArray();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ff928a0dd81d..e5dfe5425cd1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1623,6 +1623,7 @@ public class PackageParser {
return parseApkLite(apkPath, parser, attrs, flags, signatures, certificates);
} catch (XmlPullParserException | IOException | RuntimeException e) {
+ Slog.w(TAG, "Failed to parse " + apkPath, e);
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to parse " + apkPath, e);
} finally {
@@ -3160,6 +3161,10 @@ public class PackageParser {
com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
a.info.targetPackage = str != null ? str.intern() : null;
+ str = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcess);
+ a.info.targetProcess = str != null ? str.intern() : null;
+
a.info.handleProfiling = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
false);