diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 6b55b7b24ddad..8945526b352ba 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -35,6 +35,7 @@ import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -46,6 +47,8 @@ import android.util.AndroidException; import android.view.IWindowManager; import com.android.internal.os.BaseCommand; +import dalvik.system.VMRuntime; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -94,7 +97,11 @@ public class Am extends BaseCommand { " am broadcast [--user | all | current] \n" + " am instrument [-r] [-e ] [-p ] [-w]\n" + " [--user | current]\n" + - " [--no-window-animation] \n" + + " [--no-window-animation]\n" + + " [--abi ]\n : Launch the instrumented process with the " + + " selected ABI. This assumes that the process supports the" + + " selected ABI." + + " \n" + " am profile start [--user current] \n" + " am profile stop [--user current] []\n" + " am dumpheap [--user current] [-n] \n" + @@ -835,6 +842,7 @@ public class Am extends BaseCommand { Bundle args = new Bundle(); String argKey = null, argValue = null; IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); + String abi = null; String opt; while ((opt=nextOption()) != null) { @@ -853,6 +861,8 @@ public class Am extends BaseCommand { no_window_animation = true; } else if (opt.equals("--user")) { userId = parseUserArg(nextArgRequired()); + } else if (opt.equals("--abi")) { + abi = nextArgRequired(); } else { System.err.println("Error: Unknown option: " + opt); return; @@ -883,7 +893,24 @@ public class Am extends BaseCommand { wm.setAnimationScale(1, 0.0f); } - if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId)) { + if (abi != null) { + final String[] supportedAbis = Build.SUPPORTED_ABIS; + boolean matched = false; + for (String supportedAbi : supportedAbis) { + if (supportedAbi.equals(abi)) { + matched = true; + break; + } + } + + if (!matched) { + throw new AndroidException( + "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi); + } + } + + if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, + abi)) { throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 0f65454c264f1..56462ae73680b 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -943,7 +943,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM b = data.readStrongBinder(); IUiAutomationConnection c = IUiAutomationConnection.Stub.asInterface(b); int userId = data.readInt(); - boolean res = startInstrumentation(className, profileFile, fl, arguments, w, c, userId); + String abiOverride = data.readString(); + boolean res = startInstrumentation(className, profileFile, fl, arguments, w, c, userId, + abiOverride); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -3339,7 +3341,8 @@ class ActivityManagerProxy implements IActivityManager public boolean startInstrumentation(ComponentName className, String profileFile, int flags, Bundle arguments, IInstrumentationWatcher watcher, - IUiAutomationConnection connection, int userId) throws RemoteException { + IUiAutomationConnection connection, int userId, String instructionSet) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -3350,6 +3353,7 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(watcher != null ? watcher.asBinder() : null); data.writeStrongBinder(connection != null ? connection.asBinder() : null); data.writeInt(userId); + data.writeString(instructionSet); mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0); reply.readException(); boolean res = reply.readInt() != 0; diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9833c8ddaf4b1..1bd5abf1772ad 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1741,7 +1741,8 @@ class ContextImpl extends Context { arguments.setAllowFds(false); } return ActivityManagerNative.getDefault().startInstrumentation( - className, profileFile, 0, arguments, null, null, getUserId()); + className, profileFile, 0, arguments, null, null, getUserId(), + null /* ABI override */); } catch (RemoteException e) { // System has crashed, nothing we can do. } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 8434c2a01ba33..bf2d7e5969ba0 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -176,7 +176,8 @@ public interface IActivityManager extends IInterface { public boolean startInstrumentation(ComponentName className, String profileFile, int flags, Bundle arguments, IInstrumentationWatcher watcher, - IUiAutomationConnection connection, int userId) throws RemoteException; + IUiAutomationConnection connection, int userId, + String abiOverride) throws RemoteException; public void finishInstrumentation(IApplicationThread target, int resultCode, Bundle results) throws RemoteException; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fd31b4142f225..61ba6e062d18e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2834,7 +2834,7 @@ public final class ActivityManagerService extends ActivityManagerNative return app; } - startProcessLocked(app, hostingType, hostingNameStr); + startProcessLocked(app, hostingType, hostingNameStr, null /* ABI override */); return (app.pid != 0) ? app : null; } @@ -2843,7 +2843,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private final void startProcessLocked(ProcessRecord app, - String hostingType, String hostingNameStr) { + String hostingType, String hostingNameStr, String abiOverride) { if (app.pid > 0 && app.pid != MY_PID) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); @@ -2928,7 +2928,7 @@ public final class ActivityManagerService extends ActivityManagerNative debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } - String requiredAbi = app.info.cpuAbi; + String requiredAbi = (abiOverride != null) ? abiOverride : app.info.cpuAbi; if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } @@ -5020,7 +5020,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.persistent && !app.isolated) { if (!callerWillRestart) { - addAppLocked(app.info, false); + addAppLocked(app.info, false, null /* ABI override */); } else { needRestart = true; } @@ -5133,7 +5133,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); - startProcessLocked(app, "link fail", processName); + startProcessLocked(app, "link fail", processName, null /* ABI override */); return false; } @@ -5226,7 +5226,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); - startProcessLocked(app, "bind fail", processName); + startProcessLocked(app, "bind fail", processName, null /* ABI override */); return false; } @@ -5377,7 +5377,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int ip=0; ip 0 && app.pid != MY_PID) { // Goodbye! boolean removed; @@ -14312,7 +14314,7 @@ public final class ActivityManagerService extends ActivityManagerNative public boolean startInstrumentation(ComponentName className, String profileFile, int flags, Bundle arguments, IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection, - int userId) { + int userId, String abiOverride) { enforceNotIsolatedCaller("startInstrumentation"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, true, "startInstrumentation", null); @@ -14361,7 +14363,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Instrumentation can kill and relaunch even persistent processes forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId, "start instr"); - ProcessRecord app = addAppLocked(ai, false); + ProcessRecord app = addAppLocked(ai, false, abiOverride); app.instrumentationClass = className; app.instrumentationInfo = ai; app.instrumentationProfileFile = profileFile; @@ -16325,7 +16327,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.persistent) { if (app.persistent) { - addAppLocked(app.info, false); + addAppLocked(app.info, false, null /* ABI override */); } } }