Merge "Don't provide read logs for shell-initiated installations." into rvc-dev am: e0ba6d9dff
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11778056 Change-Id: I3449f64a8405e8e64d4e270277c226c6da64e5df
This commit is contained in:
@@ -205,6 +205,7 @@ public class PackageParser {
|
|||||||
public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
|
public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
|
||||||
public static final String TAG_USES_SDK = "uses-sdk";
|
public static final String TAG_USES_SDK = "uses-sdk";
|
||||||
public static final String TAG_USES_SPLIT = "uses-split";
|
public static final String TAG_USES_SPLIT = "uses-split";
|
||||||
|
public static final String TAG_PROFILEABLE = "profileable";
|
||||||
|
|
||||||
public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
|
public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
|
||||||
public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
|
public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
|
||||||
@@ -459,6 +460,9 @@ public class PackageParser {
|
|||||||
public final SigningDetails signingDetails;
|
public final SigningDetails signingDetails;
|
||||||
public final boolean coreApp;
|
public final boolean coreApp;
|
||||||
public final boolean debuggable;
|
public final boolean debuggable;
|
||||||
|
// This does not represent the actual manifest structure since the 'profilable' tag
|
||||||
|
// could be used with attributes other than 'shell'. Extend if necessary.
|
||||||
|
public final boolean profilableByShell;
|
||||||
public final boolean multiArch;
|
public final boolean multiArch;
|
||||||
public final boolean use32bitAbi;
|
public final boolean use32bitAbi;
|
||||||
public final boolean extractNativeLibs;
|
public final boolean extractNativeLibs;
|
||||||
@@ -470,15 +474,13 @@ public class PackageParser {
|
|||||||
public final int overlayPriority;
|
public final int overlayPriority;
|
||||||
|
|
||||||
public ApkLite(String codePath, String packageName, String splitName,
|
public ApkLite(String codePath, String packageName, String splitName,
|
||||||
boolean isFeatureSplit,
|
boolean isFeatureSplit, String configForSplit, String usesSplitName,
|
||||||
String configForSplit, String usesSplitName, boolean isSplitRequired,
|
boolean isSplitRequired, int versionCode, int versionCodeMajor, int revisionCode,
|
||||||
int versionCode, int versionCodeMajor,
|
int installLocation, List<VerifierInfo> verifiers, SigningDetails signingDetails,
|
||||||
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
|
boolean coreApp, boolean debuggable, boolean profilableByShell, boolean multiArch,
|
||||||
SigningDetails signingDetails, boolean coreApp,
|
boolean use32bitAbi, boolean useEmbeddedDex, boolean extractNativeLibs,
|
||||||
boolean debuggable, boolean multiArch, boolean use32bitAbi,
|
boolean isolatedSplits, String targetPackageName, boolean overlayIsStatic,
|
||||||
boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
|
int overlayPriority, int minSdkVersion, int targetSdkVersion) {
|
||||||
String targetPackageName, boolean overlayIsStatic, int overlayPriority,
|
|
||||||
int minSdkVersion, int targetSdkVersion) {
|
|
||||||
this.codePath = codePath;
|
this.codePath = codePath;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.splitName = splitName;
|
this.splitName = splitName;
|
||||||
@@ -493,6 +495,7 @@ public class PackageParser {
|
|||||||
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
|
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
|
||||||
this.coreApp = coreApp;
|
this.coreApp = coreApp;
|
||||||
this.debuggable = debuggable;
|
this.debuggable = debuggable;
|
||||||
|
this.profilableByShell = profilableByShell;
|
||||||
this.multiArch = multiArch;
|
this.multiArch = multiArch;
|
||||||
this.use32bitAbi = use32bitAbi;
|
this.use32bitAbi = use32bitAbi;
|
||||||
this.useEmbeddedDex = useEmbeddedDex;
|
this.useEmbeddedDex = useEmbeddedDex;
|
||||||
@@ -1573,6 +1576,7 @@ public class PackageParser {
|
|||||||
int revisionCode = 0;
|
int revisionCode = 0;
|
||||||
boolean coreApp = false;
|
boolean coreApp = false;
|
||||||
boolean debuggable = false;
|
boolean debuggable = false;
|
||||||
|
boolean profilableByShell = false;
|
||||||
boolean multiArch = false;
|
boolean multiArch = false;
|
||||||
boolean use32bitAbi = false;
|
boolean use32bitAbi = false;
|
||||||
boolean extractNativeLibs = true;
|
boolean extractNativeLibs = true;
|
||||||
@@ -1638,6 +1642,10 @@ public class PackageParser {
|
|||||||
final String attr = attrs.getAttributeName(i);
|
final String attr = attrs.getAttributeName(i);
|
||||||
if ("debuggable".equals(attr)) {
|
if ("debuggable".equals(attr)) {
|
||||||
debuggable = attrs.getAttributeBooleanValue(i, false);
|
debuggable = attrs.getAttributeBooleanValue(i, false);
|
||||||
|
if (debuggable) {
|
||||||
|
// Debuggable implies profileable
|
||||||
|
profilableByShell = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ("multiArch".equals(attr)) {
|
if ("multiArch".equals(attr)) {
|
||||||
multiArch = attrs.getAttributeBooleanValue(i, false);
|
multiArch = attrs.getAttributeBooleanValue(i, false);
|
||||||
@@ -1690,6 +1698,13 @@ public class PackageParser {
|
|||||||
minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
|
minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (TAG_PROFILEABLE.equals(parser.getName())) {
|
||||||
|
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
|
||||||
|
final String attr = attrs.getAttributeName(i);
|
||||||
|
if ("shell".equals(attr)) {
|
||||||
|
profilableByShell = attrs.getAttributeBooleanValue(i, profilableByShell);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,8 +1722,9 @@ public class PackageParser {
|
|||||||
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
|
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
|
||||||
configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
|
configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
|
||||||
revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
|
revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
|
||||||
multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
|
profilableByShell, multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs,
|
||||||
targetPackage, overlayIsStatic, overlayPriority, minSdkVersion, targetSdkVersion);
|
isolatedSplits, targetPackage, overlayIsStatic, overlayPriority, minSdkVersion,
|
||||||
|
targetSdkVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE
|
|||||||
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
|
||||||
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
||||||
|
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageParser;
|
import android.content.pm.PackageParser;
|
||||||
@@ -303,6 +302,7 @@ public class ApkLiteParseUtils {
|
|||||||
int revisionCode = 0;
|
int revisionCode = 0;
|
||||||
boolean coreApp = false;
|
boolean coreApp = false;
|
||||||
boolean debuggable = false;
|
boolean debuggable = false;
|
||||||
|
boolean profilableByShell = false;
|
||||||
boolean multiArch = false;
|
boolean multiArch = false;
|
||||||
boolean use32bitAbi = false;
|
boolean use32bitAbi = false;
|
||||||
boolean extractNativeLibs = true;
|
boolean extractNativeLibs = true;
|
||||||
@@ -379,6 +379,10 @@ public class ApkLiteParseUtils {
|
|||||||
switch (attr) {
|
switch (attr) {
|
||||||
case "debuggable":
|
case "debuggable":
|
||||||
debuggable = attrs.getAttributeBooleanValue(i, false);
|
debuggable = attrs.getAttributeBooleanValue(i, false);
|
||||||
|
if (debuggable) {
|
||||||
|
// Debuggable implies profileable
|
||||||
|
profilableByShell = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "multiArch":
|
case "multiArch":
|
||||||
multiArch = attrs.getAttributeBooleanValue(i, false);
|
multiArch = attrs.getAttributeBooleanValue(i, false);
|
||||||
@@ -431,6 +435,13 @@ public class ApkLiteParseUtils {
|
|||||||
minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
|
minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (PackageParser.TAG_PROFILEABLE.equals(parser.getName())) {
|
||||||
|
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
|
||||||
|
final String attr = attrs.getAttributeName(i);
|
||||||
|
if ("shell".equals(attr)) {
|
||||||
|
profilableByShell = attrs.getAttributeBooleanValue(i, profilableByShell);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,12 +456,13 @@ public class ApkLiteParseUtils {
|
|||||||
overlayPriority = 0;
|
overlayPriority = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return input.success(new PackageParser.ApkLite(codePath, packageSplit.first,
|
return input.success(
|
||||||
packageSplit.second, isFeatureSplit, configForSplit, usesSplitName, isSplitRequired,
|
new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second,
|
||||||
versionCode, versionCodeMajor, revisionCode, installLocation, verifiers,
|
isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode,
|
||||||
signingDetails, coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex,
|
versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails,
|
||||||
extractNativeLibs, isolatedSplits, targetPackage, overlayIsStatic, overlayPriority,
|
coreApp, debuggable, profilableByShell, multiArch, use32bitAbi,
|
||||||
minSdkVersion, targetSdkVersion));
|
useEmbeddedDex, extractNativeLibs, isolatedSplits, targetPackage,
|
||||||
|
overlayIsStatic, overlayPriority, minSdkVersion, targetSdkVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
|
public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ interface IIncrementalService {
|
|||||||
*/
|
*/
|
||||||
void deleteStorage(int storageId);
|
void deleteStorage(int storageId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanently disable readlogs reporting for a storage given its ID.
|
||||||
|
*/
|
||||||
|
void disableReadLogs(int storageId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting up native library directories and extract native libs onto a storage if needed.
|
* Setting up native library directories and extract native libs onto a storage if needed.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -152,6 +152,13 @@ public final class IncrementalFileStorages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanently disables readlogs.
|
||||||
|
*/
|
||||||
|
public void disableReadLogs() {
|
||||||
|
mDefaultStorage.disableReadLogs();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the states and unbinds storage instances for an installation session.
|
* Resets the states and unbinds storage instances for an installation session.
|
||||||
* TODO(b/136132412): make sure unnecessary binds are removed but useful storages are kept
|
* TODO(b/136132412): make sure unnecessary binds are removed but useful storages are kept
|
||||||
|
|||||||
@@ -417,6 +417,17 @@ public final class IncrementalStorage {
|
|||||||
private static final int INCFS_MAX_HASH_SIZE = 32; // SHA256
|
private static final int INCFS_MAX_HASH_SIZE = 32; // SHA256
|
||||||
private static final int INCFS_MAX_ADD_DATA_SIZE = 128;
|
private static final int INCFS_MAX_ADD_DATA_SIZE = 128;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanently disable readlogs collection.
|
||||||
|
*/
|
||||||
|
public void disableReadLogs() {
|
||||||
|
try {
|
||||||
|
mService.disableReadLogs(mId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize and validate v4 signature bytes.
|
* Deserialize and validate v4 signature bytes.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2108,6 +2108,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
baseApk = apk;
|
baseApk = apk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate and add Dex Metadata (.dm).
|
||||||
final File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(addedFile);
|
final File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(addedFile);
|
||||||
if (dexMetadataFile != null) {
|
if (dexMetadataFile != null) {
|
||||||
if (!FileUtils.isValidExtFilename(dexMetadataFile.getName())) {
|
if (!FileUtils.isValidExtFilename(dexMetadataFile.getName())) {
|
||||||
@@ -2295,6 +2296,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
throw new PackageManagerException(INSTALL_FAILED_MISSING_SPLIT,
|
throw new PackageManagerException(INSTALL_FAILED_MISSING_SPLIT,
|
||||||
"Missing split for " + mPackageName);
|
"Missing split for " + mPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean isInstallerShell = (mInstallerUid == Process.SHELL_UID);
|
||||||
|
if (isInstallerShell && isIncrementalInstallation() && mIncrementalFileStorages != null) {
|
||||||
|
if (!baseApk.debuggable && !baseApk.profilableByShell) {
|
||||||
|
mIncrementalFileStorages.disableReadLogs();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveAndStageFile(File origFile, File targetFile)
|
private void resolveAndStageFile(File origFile, File targetFile)
|
||||||
|
|||||||
@@ -165,6 +165,11 @@ binder::Status BinderIncrementalService::deleteStorage(int32_t storageId) {
|
|||||||
return ok();
|
return ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binder::Status BinderIncrementalService::disableReadLogs(int32_t storageId) {
|
||||||
|
mImpl.disableReadLogs(storageId);
|
||||||
|
return ok();
|
||||||
|
}
|
||||||
|
|
||||||
binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
|
binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
|
||||||
int32_t* _aidl_return) {
|
int32_t* _aidl_return) {
|
||||||
*_aidl_return = mImpl.makeDir(storageId, path);
|
*_aidl_return = mImpl.makeDir(storageId, path);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
std::vector<uint8_t>* _aidl_return) final;
|
std::vector<uint8_t>* _aidl_return) final;
|
||||||
binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
|
binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
|
||||||
binder::Status deleteStorage(int32_t storageId) final;
|
binder::Status deleteStorage(int32_t storageId) final;
|
||||||
|
binder::Status disableReadLogs(int32_t storageId) final;
|
||||||
binder::Status configureNativeBinaries(int32_t storageId, const std::string& apkFullPath,
|
binder::Status configureNativeBinaries(int32_t storageId, const std::string& apkFullPath,
|
||||||
const std::string& libDirRelativePath,
|
const std::string& libDirRelativePath,
|
||||||
const std::string& abi, bool extractNativeLibs,
|
const std::string& abi, bool extractNativeLibs,
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ struct Constants {
|
|||||||
static constexpr auto storagePrefix = "st"sv;
|
static constexpr auto storagePrefix = "st"sv;
|
||||||
static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
|
static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
|
||||||
static constexpr auto infoMdName = ".info"sv;
|
static constexpr auto infoMdName = ".info"sv;
|
||||||
|
static constexpr auto readLogsDisabledMarkerName = ".readlogs_disabled"sv;
|
||||||
static constexpr auto libDir = "lib"sv;
|
static constexpr auto libDir = "lib"sv;
|
||||||
static constexpr auto libSuffix = ".so"sv;
|
static constexpr auto libSuffix = ".so"sv;
|
||||||
static constexpr auto blockSize = 4096;
|
static constexpr auto blockSize = 4096;
|
||||||
@@ -172,6 +173,13 @@ std::string makeBindMdName() {
|
|||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool checkReadLogsDisabledMarker(std::string_view root) {
|
||||||
|
const auto markerPath = path::c_str(path::join(root, constants().readLogsDisabledMarkerName));
|
||||||
|
struct stat st;
|
||||||
|
return (::stat(markerPath, &st) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
IncrementalService::IncFsMount::~IncFsMount() {
|
IncrementalService::IncFsMount::~IncFsMount() {
|
||||||
@@ -618,6 +626,32 @@ StorageId IncrementalService::findStorageId(std::string_view path) const {
|
|||||||
return it->second->second.storage;
|
return it->second->second.storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IncrementalService::disableReadLogs(StorageId storageId) {
|
||||||
|
std::unique_lock l(mLock);
|
||||||
|
const auto ifs = getIfsLocked(storageId);
|
||||||
|
if (!ifs) {
|
||||||
|
LOG(ERROR) << "disableReadLogs failed, invalid storageId: " << storageId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ifs->readLogsEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ifs->disableReadLogs();
|
||||||
|
l.unlock();
|
||||||
|
|
||||||
|
const auto metadata = constants().readLogsDisabledMarkerName;
|
||||||
|
if (auto err = mIncFs->makeFile(ifs->control,
|
||||||
|
path::join(ifs->root, constants().mount,
|
||||||
|
constants().readLogsDisabledMarkerName),
|
||||||
|
0777, idFromMetadata(metadata), {})) {
|
||||||
|
//{.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) {
|
||||||
|
LOG(ERROR) << "Failed to make marker file for storageId: " << storageId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStorageParams(storageId, /*enableReadLogs=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLogs) {
|
int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLogs) {
|
||||||
const auto ifs = getIfs(storageId);
|
const auto ifs = getIfs(storageId);
|
||||||
if (!ifs) {
|
if (!ifs) {
|
||||||
@@ -627,6 +661,11 @@ int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLog
|
|||||||
|
|
||||||
const auto& params = ifs->dataLoaderStub->params();
|
const auto& params = ifs->dataLoaderStub->params();
|
||||||
if (enableReadLogs) {
|
if (enableReadLogs) {
|
||||||
|
if (!ifs->readLogsEnabled()) {
|
||||||
|
LOG(ERROR) << "setStorageParams failed, readlogs disabled for storageId: " << storageId;
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto status = mAppOpsManager->checkPermission(kDataUsageStats, kOpUsage,
|
if (auto status = mAppOpsManager->checkPermission(kDataUsageStats, kOpUsage,
|
||||||
params.packageName.c_str());
|
params.packageName.c_str());
|
||||||
!status.isOk()) {
|
!status.isOk()) {
|
||||||
@@ -1072,6 +1111,11 @@ std::unordered_set<std::string_view> IncrementalService::adoptMountedInstances()
|
|||||||
std::move(control), *this);
|
std::move(control), *this);
|
||||||
cleanupFiles.release(); // ifs will take care of that now
|
cleanupFiles.release(); // ifs will take care of that now
|
||||||
|
|
||||||
|
// Check if marker file present.
|
||||||
|
if (checkReadLogsDisabledMarker(root)) {
|
||||||
|
ifs->disableReadLogs();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, metadata::BindPoint>> permanentBindPoints;
|
std::vector<std::pair<std::string, metadata::BindPoint>> permanentBindPoints;
|
||||||
auto d = openDir(root);
|
auto d = openDir(root);
|
||||||
while (auto e = ::readdir(d.get())) {
|
while (auto e = ::readdir(d.get())) {
|
||||||
@@ -1243,6 +1287,11 @@ bool IncrementalService::mountExistingImage(std::string_view root) {
|
|||||||
ifs->mountId = mount.storage().id();
|
ifs->mountId = mount.storage().id();
|
||||||
mNextId = std::max(mNextId, ifs->mountId + 1);
|
mNextId = std::max(mNextId, ifs->mountId + 1);
|
||||||
|
|
||||||
|
// Check if marker file present.
|
||||||
|
if (checkReadLogsDisabledMarker(mountTarget)) {
|
||||||
|
ifs->disableReadLogs();
|
||||||
|
}
|
||||||
|
|
||||||
// DataLoader params
|
// DataLoader params
|
||||||
DataLoaderParamsParcel dataLoaderParams;
|
DataLoaderParamsParcel dataLoaderParams;
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ public:
|
|||||||
Permanent = 1,
|
Permanent = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StorageFlags {
|
||||||
|
ReadLogsEnabled = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static FileId idFromMetadata(std::span<const uint8_t> metadata);
|
static FileId idFromMetadata(std::span<const uint8_t> metadata);
|
||||||
static inline FileId idFromMetadata(std::span<const char> metadata) {
|
static inline FileId idFromMetadata(std::span<const char> metadata) {
|
||||||
return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
|
return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
|
||||||
@@ -116,6 +120,7 @@ public:
|
|||||||
int unbind(StorageId storage, std::string_view target);
|
int unbind(StorageId storage, std::string_view target);
|
||||||
void deleteStorage(StorageId storage);
|
void deleteStorage(StorageId storage);
|
||||||
|
|
||||||
|
void disableReadLogs(StorageId storage);
|
||||||
int setStorageParams(StorageId storage, bool enableReadLogs);
|
int setStorageParams(StorageId storage, bool enableReadLogs);
|
||||||
|
|
||||||
int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
|
int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
|
||||||
@@ -264,6 +269,7 @@ private:
|
|||||||
const std::string root;
|
const std::string root;
|
||||||
Control control;
|
Control control;
|
||||||
/*const*/ MountId mountId;
|
/*const*/ MountId mountId;
|
||||||
|
int32_t flags = StorageFlags::ReadLogsEnabled;
|
||||||
StorageMap storages;
|
StorageMap storages;
|
||||||
BindMap bindPoints;
|
BindMap bindPoints;
|
||||||
DataLoaderStubPtr dataLoaderStub;
|
DataLoaderStubPtr dataLoaderStub;
|
||||||
@@ -282,6 +288,9 @@ private:
|
|||||||
|
|
||||||
StorageMap::iterator makeStorage(StorageId id);
|
StorageMap::iterator makeStorage(StorageId id);
|
||||||
|
|
||||||
|
void disableReadLogs() { flags &= ~StorageFlags::ReadLogsEnabled; }
|
||||||
|
int32_t readLogsEnabled() const { return (flags & StorageFlags::ReadLogsEnabled); }
|
||||||
|
|
||||||
static void cleanupFilesystem(std::string_view root);
|
static void cleanupFilesystem(std::string_view root);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -929,6 +929,34 @@ TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) {
|
|||||||
ASSERT_GE(mDataLoader->setStorageParams(true), 0);
|
ASSERT_GE(mDataLoader->setStorageParams(true), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccessAndDisabled) {
|
||||||
|
mVold->mountIncFsSuccess();
|
||||||
|
mIncFs->makeFileSuccess();
|
||||||
|
mVold->bindMountSuccess();
|
||||||
|
mVold->setIncFsMountOptionsSuccess();
|
||||||
|
mDataLoaderManager->bindToDataLoaderSuccess();
|
||||||
|
mDataLoaderManager->getDataLoaderSuccess();
|
||||||
|
mAppOpsManager->checkPermissionSuccess();
|
||||||
|
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_));
|
||||||
|
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
|
||||||
|
// Enabling and then disabling readlogs.
|
||||||
|
EXPECT_CALL(*mVold, setIncFsMountOptions(_, true)).Times(1);
|
||||||
|
EXPECT_CALL(*mVold, setIncFsMountOptions(_, false)).Times(1);
|
||||||
|
// After setIncFsMountOptions succeeded expecting to start watching.
|
||||||
|
EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(1);
|
||||||
|
// Not expecting callback removal.
|
||||||
|
EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
|
||||||
|
TemporaryDir tempDir;
|
||||||
|
int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
|
||||||
|
IncrementalService::CreateOptions::CreateNew,
|
||||||
|
{}, {}, {});
|
||||||
|
ASSERT_GE(storageId, 0);
|
||||||
|
ASSERT_GE(mDataLoader->setStorageParams(true), 0);
|
||||||
|
// Now disable.
|
||||||
|
mIncrementalService->disableReadLogs(storageId);
|
||||||
|
ASSERT_EQ(mDataLoader->setStorageParams(true), -EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccessAndPermissionChanged) {
|
TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccessAndPermissionChanged) {
|
||||||
mVold->mountIncFsSuccess();
|
mVold->mountIncFsSuccess();
|
||||||
mIncFs->makeFileSuccess();
|
mIncFs->makeFileSuccess();
|
||||||
|
|||||||
Reference in New Issue
Block a user