Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8dcfefd6 authored by Narayan Kamath's avatar Narayan Kamath
Browse files

Support an ABI flag for instrumentation.

Allows us to choose what ABI a process uses when
launching it with "adb shell am instrument", for eg.

adb shell am instrument --abi arm64-v8a component/runner

Note that we only perform very basic validation of the
ABI. In general, there is no guarantee that the app will
launch with the instruction set we choose, for eg. if it
has native libraries that are for a different ABI.

bug: 14453227

Change-Id: Ifb7e89b53675080dc87941091ee5ac360f218d7f
parent 402120a2
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -43,6 +44,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;
@@ -91,7 +94,11 @@ public class Am extends BaseCommand {
                "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
                "               [--user <USER_ID> | current]\n" +
                "               [--no-window-animation] <COMPONENT>\n" +
                "               [--no-window-animation]\n" +
                "               [--abi <ABI>]\n : Launch the instrumented process with the "  +
                "                   selected ABI. This assumes that the process supports the" +
                "                   selected ABI." +
                "               <COMPONENT>\n" +
                "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
                "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
                "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
@@ -813,6 +820,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) {
@@ -831,6 +839,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;
@@ -861,7 +871,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());
        }

+6 −2
Original line number Diff line number Diff line
@@ -914,7 +914,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;
@@ -3173,7 +3175,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);
@@ -3184,6 +3187,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;
+2 −1
Original line number Diff line number Diff line
@@ -1611,7 +1611,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.
        }
+2 −1
Original line number Diff line number Diff line
@@ -172,7 +172,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;

+16 −14
Original line number Diff line number Diff line
@@ -2686,7 +2686,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;
    }
@@ -2695,7 +2695,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);
@@ -2780,7 +2780,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];
            }
@@ -4804,7 +4804,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;
                }
@@ -4912,7 +4912,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;
        }
@@ -5005,7 +5005,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;
        }
@@ -5174,7 +5174,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                for (int ip=0; ip<NP; ip++) {
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
                            + procs.get(ip));
                    startProcessLocked(procs.get(ip), "on-hold", null);
                    startProcessLocked(procs.get(ip), "on-hold", null, null /* ABI override */);
                }
            }
            
@@ -8175,7 +8175,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        return new ProcessRecord(stats, info, proc, uid);
    }
    final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
    final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
            String abiOverride) {
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(info.processName, info.uid, true);
@@ -8210,7 +8211,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
            mPersistentStartingProcesses.add(app);
            startProcessLocked(app, "added application", app.processName);
            startProcessLocked(app, "added application", app.processName,
                    abiOverride);
        }
        return app;
@@ -9396,7 +9398,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                                = (ApplicationInfo)apps.get(i);
                            if (info != null &&
                                    !info.packageName.equals("android")) {
                                addAppLocked(info, false);
                                addAppLocked(info, false, null /* ABI override */);
                            }
                        }
                    }
@@ -12562,7 +12564,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            // We have components that still need to be running in the
            // process, so re-launch it.
            mProcessNames.put(app.processName, app.uid, app);
            startProcessLocked(app, "restart", app.processName);
            startProcessLocked(app, "restart", app.processName, null /* ABI override */);
        } else if (app.pid > 0 && app.pid != MY_PID) {
            // Goodbye!
            synchronized (mPidsSelfLocked) {
@@ -13850,7 +13852,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);
@@ -13899,7 +13901,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            // Instrumentation can kill and relaunch even persistent processes
            forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId,
                    "start instr");
            ProcessRecord app = addAppLocked(ai, false);
            ProcessRecord app = addAppLocked(ai, false, abiOverride);
            app.instrumentationClass = className;
            app.instrumentationInfo = ai;
            app.instrumentationProfileFile = profileFile;
@@ -15829,7 +15831,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    
                    if (app.persistent) {
                        if (app.persistent) {
                            addAppLocked(app.info, false);
                            addAppLocked(app.info, false, null /* ABI override */);
                        }
                    }
                }