Start OP_NO_ISOLATED_STORAGE on am instrument --no-isolated-storage

This provides a signal for MediaProvider to whitelist access for full
external storage access.

Here is an overview of how the flow looks like:

1. When app is started within instrumentation with --no-isolated-storage
flag, ActivityManagerService will grant OP_NO_ISOLATED_STORAGE to that
package.
2. MediaProvider will note the OP_NO_ISOLATED_STORAGE app op as fallback
in case app doesn't have MANAGE_EXTERNAL_STORAGE permissions.
3. When instrumentation finishes, ActivityManagerService will change
mode of OP_NO_ISOLATED_STORAGE app op to MODE_ERRORED.

Test: atest ExternalStorageHostTest
Bug: 149894531
Change-Id: I51cd87e5e887b887fd8ac7a1a7ffff208266ffa8
This commit is contained in:
Nikita Ioffe
2020-06-08 22:24:06 +01:00
parent 95e41f279d
commit ac095e5a1d
5 changed files with 36 additions and 7 deletions

View File

@ -17,8 +17,8 @@
package com.android.commands.am;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
@ -512,7 +512,7 @@ public class Instrument {
flags |= INSTR_FLAG_DISABLE_TEST_API_CHECKS;
}
if (disableIsolatedStorage) {
flags |= INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
flags |= INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
}
if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
abi)) {

View File

@ -159,10 +159,10 @@ public class ActivityManager {
*/
public static final int INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
/**
* Mount full external storage for the newly started instrumentation.
* Grant full access to the external storage for the newly started instrumentation.
* @hide
*/
public static final int INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL = 1 << 1;
public static final int INSTR_FLAG_DISABLE_ISOLATED_STORAGE = 1 << 1;
/**
* Disable test API access for the newly started instrumentation.

View File

@ -1120,9 +1120,12 @@ public class AppOpsManager {
public static final int OP_AUTO_REVOKE_MANAGED_BY_INSTALLER =
AppProtoEnums.APP_OP_AUTO_REVOKE_MANAGED_BY_INSTALLER;
/** @hide */
public static final int OP_NO_ISOLATED_STORAGE = AppProtoEnums.APP_OP_NO_ISOLATED_STORAGE;
/** @hide */
@UnsupportedAppUsage
public static final int _NUM_OP = 99;
public static final int _NUM_OP = 100;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@ -1433,6 +1436,12 @@ public class AppOpsManager {
@SystemApi
public static final String OPSTR_LOADER_USAGE_STATS = "android:loader_usage_stats";
/**
* AppOp granted to apps that we are started via {@code am instrument -e --no-isolated-storage}
*
* @hide
*/
public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@ -1622,6 +1631,7 @@ public class AppOpsManager {
OP_DEPRECATED_1, // deprecated
OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, //AUTO_REVOKE_PERMISSIONS_IF_UNUSED
OP_AUTO_REVOKE_MANAGED_BY_INSTALLER, //OP_AUTO_REVOKE_MANAGED_BY_INSTALLER
OP_NO_ISOLATED_STORAGE, // NO_ISOLATED_STORAGE
};
/**
@ -1727,6 +1737,7 @@ public class AppOpsManager {
"", // deprecated
OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER,
OPSTR_NO_ISOLATED_STORAGE,
};
/**
@ -1833,6 +1844,7 @@ public class AppOpsManager {
"deprecated",
"AUTO_REVOKE_PERMISSIONS_IF_UNUSED",
"AUTO_REVOKE_MANAGED_BY_INSTALLER",
"NO_ISOLATED_STORAGE",
};
/**
@ -1940,6 +1952,7 @@ public class AppOpsManager {
null, // deprecated operation
null, // no permission for OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
null, // no permission for OP_AUTO_REVOKE_MANAGED_BY_INSTALLER
null, // no permission for OP_NO_ISOLATED_STORAGE
};
/**
@ -2047,6 +2060,7 @@ public class AppOpsManager {
null, // deprecated operation
null, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
null, // AUTO_REVOKE_MANAGED_BY_INSTALLER
null, // NO_ISOLATED_STORAGE
};
/**
@ -2153,6 +2167,7 @@ public class AppOpsManager {
null, // deprecated operation
null, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
null, // AUTO_REVOKE_MANAGED_BY_INSTALLER
null, // NO_ISOLATED_STORAGE
};
/**
@ -2258,6 +2273,7 @@ public class AppOpsManager {
AppOpsManager.MODE_IGNORED, // deprecated operation
AppOpsManager.MODE_DEFAULT, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
AppOpsManager.MODE_ALLOWED, // OP_AUTO_REVOKE_MANAGED_BY_INSTALLER
AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE
};
/**
@ -2367,6 +2383,7 @@ public class AppOpsManager {
false, // deprecated operation
false, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
false, // AUTO_REVOKE_MANAGED_BY_INSTALLER
true, // NO_ISOLATED_STORAGE
};
/**

View File

@ -206,4 +206,5 @@ enum AppOpEnum {
APP_OP_DEPRECATED_1 = 96 [deprecated = true];
APP_OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97;
APP_OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98;
APP_OP_NO_ISOLATED_STORAGE = 99;
}

View File

@ -24,8 +24,8 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@ -16904,8 +16904,9 @@ public class ActivityManagerService extends IActivityManager.Stub
"disable hidden API checks");
}
// TODO(b/158750470): remove
final boolean mountExtStorageFull = isCallerShell()
&& (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0;
&& (flags & INSTR_FLAG_DISABLE_ISOLATED_STORAGE) != 0;
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
@ -16927,6 +16928,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!mActiveInstrumentation.contains(activeInstr)) {
mActiveInstrumentation.add(activeInstr);
}
if ((flags & INSTR_FLAG_DISABLE_ISOLATED_STORAGE) != 0) {
// Allow OP_NO_ISOLATED_STORAGE app op for the package running instrumentation with
// --no-isolated-storage flag.
mAppOpsService.setMode(AppOpsManager.OP_NO_ISOLATED_STORAGE, ai.uid,
ii.packageName, AppOpsManager.MODE_ALLOWED);
}
Binder.restoreCallingIdentity(origId);
}
@ -17017,6 +17025,9 @@ public class ActivityManagerService extends IActivityManager.Stub
// Can't call out of the system process with a lock held, so post a message.
if (instr.mUiAutomationConnection != null) {
// Go back to the default mode of denying OP_NO_ISOLATED_STORAGE app op.
mAppOpsService.setMode(AppOpsManager.OP_NO_ISOLATED_STORAGE, app.uid,
app.info.packageName, AppOpsManager.MODE_ERRORED);
mAppOpsService.setAppOpsServiceDelegate(null);
getPermissionManagerInternalLocked().setCheckPermissionDelegate(null);
mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,