diff options
6 files changed, 80 insertions, 50 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index c04e61b77274..41d546f6d603 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -174,6 +174,8 @@ public class Am extends BaseCommand { instrument.noWindowAnimation = true; } else if (opt.equals("--no-hidden-api-checks")) { instrument.disableHiddenApiChecks = true; + } else if (opt.equals("--no-isolated-storage")) { + instrument.disableIsolatedStorage = true; } else if (opt.equals("--user")) { instrument.userId = parseUserArg(nextArgRequired()); } else if (opt.equals("--abi")) { diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java index 0dade0b2ba81..70baa8702ba9 100644 --- a/cmds/am/src/com/android/commands/am/Instrument.java +++ b/cmds/am/src/com/android/commands/am/Instrument.java @@ -16,6 +16,9 @@ package com.android.commands.am; +import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; +import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; + import android.app.IActivityManager; import android.app.IInstrumentationWatcher; import android.app.Instrumentation; @@ -74,16 +77,13 @@ public class Instrument { String logPath = null; public boolean noWindowAnimation = false; public boolean disableHiddenApiChecks = false; + public boolean disableIsolatedStorage = false; public String abi = null; public int userId = UserHandle.USER_CURRENT; public Bundle args = new Bundle(); // Required public String componentNameArg; - // Disable hidden API checks for the newly started instrumentation. - // Must be kept in sync with ActivityManagerService. - private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0; - /** * Construct the instrument command runner. */ @@ -480,7 +480,13 @@ public class Instrument { } // Start the instrumentation - int flags = disableHiddenApiChecks ? INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS : 0; + int flags = 0; + if (disableHiddenApiChecks) { + flags |= INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; + } + if (disableIsolatedStorage) { + flags |= INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; + } if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId, abi)) { throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 14b8ae45d989..7330da323f47 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -137,6 +137,17 @@ public class ActivityManager { private static final int FIRST_START_NON_FATAL_ERROR_CODE = 100; private static final int LAST_START_NON_FATAL_ERROR_CODE = 199; + /** + * Disable hidden API checks for the newly started instrumentation. + * @hide + */ + public static final int INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0; + /** + * Mount full external storage for the newly started instrumentation. + * @hide + */ + public static final int INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL = 1 << 1; + static final class UidObserver extends IUidObserver.Stub { final OnUidImportanceListener mListener; final Context mContext; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6f043ecee27a..b9aa34e45ff1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -22,6 +22,8 @@ import static android.Manifest.permission.FILTER_EVENTS; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.REMOVE_TASKS; +import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; +import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; @@ -461,10 +463,6 @@ public class ActivityManagerService extends IActivityManager.Stub static final int BROADCAST_FG_TIMEOUT = 10*1000; static final int BROADCAST_BG_TIMEOUT = 60*1000; - // Disable hidden API checks for the newly started instrumentation. - // Must be kept in sync with Am. - private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0; - public static final int MY_PID = myPid(); static final String[] EMPTY_STRING_ARRAY = new String[0]; @@ -7122,13 +7120,13 @@ public class ActivityManagerService extends IActivityManager.Stub final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, String abiOverride) { return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */, - abiOverride); + false /* mountExtStorageFull */, abiOverride); } // TODO: Move to ProcessList? @GuardedBy("this") final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, - boolean disableHiddenApiChecks, String abiOverride) { + boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) { ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName, @@ -7161,7 +7159,7 @@ public class ActivityManagerService extends IActivityManager.Stub mPersistentStartingProcesses.add(app); mProcessList.startProcessLocked(app, "added application", customProcess != null ? customProcess : app.processName, disableHiddenApiChecks, - abiOverride); + mountExtStorageFull, abiOverride); } return app; @@ -14687,11 +14685,13 @@ public class ActivityManagerService extends IActivityManager.Stub activeInstr.mResultClass = className; boolean disableHiddenApiChecks = ai.usesNonSdkApi() - || (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0; + || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0; if (disableHiddenApiChecks) { enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS, "disable hidden API checks"); } + final boolean mountExtStorageFull = isCallerShell() + && (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0; final long origId = Binder.clearCallingIdentity(); // Instrumentation can kill and relaunch even persistent processes @@ -14704,7 +14704,7 @@ public class ActivityManagerService extends IActivityManager.Stub } ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, - abiOverride); + mountExtStorageFull, abiOverride); app.setActiveInstrumentation(activeInstr); activeInstr.mFinished = false; activeInstr.mRunningProcesses.add(app); @@ -14717,6 +14717,11 @@ public class ActivityManagerService extends IActivityManager.Stub return true; } + private boolean isCallerShell() { + final int callingUid = Binder.getCallingUid(); + return callingUid == SHELL_UID || callingUid == ROOT_UID; + } + /** * Report errors that occur while attempting to start Instrumentation. Always writes the * error to the logs, but if somebody is watching, send the report there too. This enables diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 692b2d433dbc..96601a20471b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -17,14 +17,13 @@ package com.android.server.am; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityTaskManager.RESIZE_MODE_USER; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; -import static android.app.ActivityTaskManager.INVALID_TASK_ID; - import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityTaskManager; @@ -2902,6 +2901,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --receiver-permission <PERMISSION>: Require receiver to hold permission."); pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]"); pw.println(" [--user <USER_ID> | current] [--no-hidden-api-checks]"); + pw.println(" [--no-isolated-storage]"); pw.println(" [--no-window-animation] [--abi <ABI>] <COMPONENT>"); pw.println(" Start an Instrumentation. Typically this target <COMPONENT> is in the"); pw.println(" form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there"); @@ -2920,6 +2920,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --user <USER_ID> | current: Specify user instrumentation runs in;"); pw.println(" current user if not specified."); pw.println(" --no-hidden-api-checks: disable restrictions on use of hidden API."); + pw.println(" --no-isolated-storage: don't use isolated storage sandbox and "); + pw.println(" mount full external storage"); pw.println(" --no-window-animation: turn off window animations while running."); pw.println(" --abi <ABI>: Launch the instrumented process with the selected ABI."); pw.println(" This assumes that the process supports the selected ABI."); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 3f172cc11468..cb6061a47351 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -18,7 +18,6 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; import static android.app.ActivityThread.PROC_START_SEQ_IDENT; -import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO; import static android.os.Process.FIRST_ISOLATED_UID; import static android.os.Process.LAST_ISOLATED_UID; @@ -28,6 +27,7 @@ import static android.os.Process.getFreeMemory; import static android.os.Process.getTotalMemory; import static android.os.Process.killProcessQuiet; import static android.os.Process.startWebView; +import static android.os.storage.StorageManager.PROP_ISOLATED_STORAGE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES; @@ -45,17 +45,6 @@ import static com.android.server.am.ActivityManagerService.TAG_PROCESSES; import static com.android.server.am.ActivityManagerService.TAG_PSS; import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS; -import dalvik.system.VMRuntime; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppProtoEnums; @@ -64,11 +53,14 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.content.res.Resources; +import android.graphics.Point; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.FactoryTest; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -77,6 +69,17 @@ import android.os.Process; import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.Trace; +import android.os.UserHandle; +import android.os.storage.StorageManagerInternal; +import android.text.TextUtils; +import android.util.EventLog; +import android.util.LongSparseArray; +import android.util.Slog; +import android.util.SparseArray; +import android.util.StatsLog; +import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -91,21 +94,16 @@ import com.android.server.Watchdog; import com.android.server.pm.dex.DexManager; import com.android.server.wm.WindowManagerService; -import android.content.res.Resources; -import android.graphics.Point; -import android.os.SystemProperties; -import android.net.LocalSocketAddress; -import android.net.LocalSocket; -import android.os.Trace; -import android.os.UserHandle; -import android.os.storage.StorageManagerInternal; -import android.text.TextUtils; -import android.util.EventLog; -import android.util.LongSparseArray; -import android.util.Slog; -import android.util.SparseArray; -import android.util.StatsLog; -import android.view.Display; +import dalvik.system.VMRuntime; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Activity manager code dealing with processes. @@ -1182,7 +1180,8 @@ public final class ProcessList { */ @GuardedBy("mService") boolean startProcessLocked(ProcessRecord app, String hostingType, - String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) { + String hostingNameStr, boolean disableHiddenApiChecks, boolean mountExtStorageFull, + String abiOverride) { if (app.pendingStart) { return true; } @@ -1224,10 +1223,15 @@ public final class ProcessList { final IPackageManager pm = AppGlobals.getPackageManager(); permGids = pm.getPackageGids(app.info.packageName, MATCH_DIRECT_BOOT_AUTO, app.userId); - StorageManagerInternal storageManagerInternal = LocalServices.getService( - StorageManagerInternal.class); - mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, - app.info.packageName); + if (SystemProperties.getBoolean(PROP_ISOLATED_STORAGE, false) + && mountExtStorageFull) { + mountExternal = Zygote.MOUNT_EXTERNAL_FULL; + } else { + StorageManagerInternal storageManagerInternal = LocalServices.getService( + StorageManagerInternal.class); + mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, + app.info.packageName); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1482,7 +1486,7 @@ public final class ProcessList { final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride) { return startProcessLocked(app, hostingType, hostingNameStr, - false /* disableHiddenApiChecks */, abiOverride); + false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride); } @GuardedBy("mService") |