Merge changes from topic "LOADER_USAGE_STATS" into rvc-dev am: 50e0244012 am: 3ea7adf007
Change-Id: Idea21be4a3c6b191ab12b62fe11a61be535c4391
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.os.incremental;
|
||||
/* @hide */
|
||||
parcelable IncrementalFileSystemControlParcel {
|
||||
ParcelFileDescriptor cmd;
|
||||
ParcelFileDescriptor pendingReads;
|
||||
ParcelFileDescriptor log;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.os.incremental;
|
||||
/* @hide */
|
||||
interface IIncrementalService {
|
||||
int openStorage(in @utf8InCpp String path);
|
||||
int createStorage(in @utf8InCpp String path, in android.content.pm.DataLoaderParamsParcel params, in android.content.pm.IDataLoaderStatusListener listener, int createMode);
|
||||
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
|
||||
int makeBindMount(int storageId, in @utf8InCpp String sourcePath, in @utf8InCpp String targetFullPath, int bindType);
|
||||
int deleteBindMount(int storageId, in @utf8InCpp String targetFullPath);
|
||||
int makeDirectory(int storageId, in @utf8InCpp String path);
|
||||
int makeDirectories(int storageId, in @utf8InCpp String path);
|
||||
int makeFile(int storageId, in @utf8InCpp String path, in android.os.incremental.IncrementalNewFileParams params);
|
||||
int makeFileFromRange(int storageId, in @utf8InCpp String targetPath, in @utf8InCpp String sourcePath, long start, long end);
|
||||
int makeLink(int sourceStorageId, in @utf8InCpp String sourcePath, int destStorageId, in @utf8InCpp String destPath);
|
||||
int unlink(int storageId, in @utf8InCpp String path);
|
||||
boolean isFileRangeLoaded(int storageId, in @utf8InCpp String path, long start, long end);
|
||||
byte[] getMetadataByPath(int storageId, in @utf8InCpp String path);
|
||||
byte[] getMetadataById(int storageId, in byte[] fileId);
|
||||
boolean startLoading(int storageId);
|
||||
void deleteStorage(int storageId);
|
||||
boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi);
|
||||
const int CREATE_MODE_TEMPORARY_BIND = 1;
|
||||
const int CREATE_MODE_PERMANENT_BIND = 2;
|
||||
const int CREATE_MODE_CREATE = 4;
|
||||
const int CREATE_MODE_OPEN_EXISTING = 8;
|
||||
const int BIND_TEMPORARY = 0;
|
||||
const int BIND_PERMANENT = 1;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.os.incremental;
|
||||
/* @hide */
|
||||
parcelable IncrementalNewFileParams {
|
||||
long size;
|
||||
byte[] fileId;
|
||||
byte[] metadata;
|
||||
@nullable byte[] signature;
|
||||
}
|
||||
@@ -37,6 +37,13 @@ interface IIncrementalService {
|
||||
int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, in IDataLoaderStatusListener listener, int createMode);
|
||||
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
|
||||
|
||||
/**
|
||||
* Changes storage params. Returns 0 on success, and -errno on failure.
|
||||
* Use enableReadLogs to switch pages read logs reporting on and off.
|
||||
* Returns 0 on success, and - errno on failure: permission check or remount.
|
||||
*/
|
||||
int setStorageParams(int storageId, boolean enableReadLogs);
|
||||
|
||||
/**
|
||||
* Bind-mounts a path under a storage to a full path. Can be permanent or temporary.
|
||||
*/
|
||||
|
||||
@@ -19,11 +19,13 @@ package android.os.incremental;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemService;
|
||||
import android.content.Context;
|
||||
import android.content.pm.DataLoaderParams;
|
||||
import android.content.pm.IDataLoaderStatusListener;
|
||||
import android.os.RemoteException;
|
||||
import android.system.ErrnoException;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -319,6 +321,23 @@ public final class IncrementalManager {
|
||||
return nativeUnsafeGetFileSignature(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets storage parameters.
|
||||
*
|
||||
* @param enableReadLogs - enables or disables read logs. Caller has to have a permission.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.LOADER_USAGE_STATS)
|
||||
public void setStorageParams(int storageId, boolean enableReadLogs) throws ErrnoException {
|
||||
try {
|
||||
int res = mService.setStorageParams(storageId, enableReadLogs);
|
||||
if (res < 0) {
|
||||
throw new ErrnoException("setStorageParams", -res);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/* Native methods */
|
||||
private static native boolean nativeIsEnabled();
|
||||
private static native boolean nativeIsIncrementalPath(@NonNull String path);
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.DataLoaderParams;
|
||||
import android.content.pm.DataLoaderParamsParcel;
|
||||
@@ -31,6 +32,8 @@ import android.content.pm.InstallationFile;
|
||||
import android.content.pm.InstallationFileParcel;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.incremental.IncrementalManager;
|
||||
import android.system.ErrnoException;
|
||||
import android.util.ExceptionUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -208,6 +211,25 @@ public abstract class DataLoaderService extends Service {
|
||||
private final long mNativeInstance;
|
||||
}
|
||||
|
||||
/* Used by native FileSystemConnector. */
|
||||
private boolean setStorageParams(int storageId, boolean enableReadLogs) {
|
||||
IncrementalManager incrementalManager = (IncrementalManager) getSystemService(
|
||||
Context.INCREMENTAL_SERVICE);
|
||||
if (incrementalManager == null) {
|
||||
Slog.e(TAG, "Failed to obtain incrementalManager: " + storageId);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// This has to be done directly in incrementalManager as the storage
|
||||
// might be missing still.
|
||||
incrementalManager.setStorageParams(storageId, enableReadLogs);
|
||||
} catch (ErrnoException e) {
|
||||
Slog.e(TAG, "Failed to set params for storage: " + storageId, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Native methods */
|
||||
private native boolean nativeCreateDataLoader(int storageId,
|
||||
@NonNull FileSystemControlParcel control,
|
||||
|
||||
@@ -392,6 +392,7 @@ private:
|
||||
mArgs = params.arguments();
|
||||
mIfs = ifs;
|
||||
mStatusListener = statusListener;
|
||||
mIfs->setParams({.readLogsEnabled = true});
|
||||
return true;
|
||||
}
|
||||
bool onStart() final { return true; }
|
||||
|
||||
@@ -155,6 +155,11 @@ binder::Status BinderIncrementalService::deleteStorage(int32_t storageId) {
|
||||
return ok();
|
||||
}
|
||||
|
||||
binder::Status BinderIncrementalService::setStorageParams(int32_t storage, bool enableReadLogs, int32_t* _aidl_return) {
|
||||
*_aidl_return = mImpl.setStorageParams(storage, enableReadLogs);
|
||||
return ok();
|
||||
}
|
||||
|
||||
binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
|
||||
int32_t* _aidl_return) {
|
||||
*_aidl_return = mImpl.makeDir(storageId, path);
|
||||
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
binder::Status configureNativeBinaries(int32_t storageId, const std::string& apkFullPath,
|
||||
const std::string& libDirRelativePath,
|
||||
const std::string& abi, bool* _aidl_return) final;
|
||||
binder::Status setStorageParams(int32_t storage, bool enableReadLogs, int32_t* _aidl_return) final;
|
||||
|
||||
private:
|
||||
android::incremental::IncrementalService mImpl;
|
||||
|
||||
@@ -563,6 +563,36 @@ StorageId IncrementalService::findStorageId(std::string_view path) const {
|
||||
return it->second->second.storage;
|
||||
}
|
||||
|
||||
int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLogs) {
|
||||
const auto ifs = getIfs(storageId);
|
||||
if (!ifs) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
using unique_fd = ::android::base::unique_fd;
|
||||
::android::os::incremental::IncrementalFileSystemControlParcel control;
|
||||
control.cmd.reset(unique_fd(dup(ifs->control.cmd())));
|
||||
control.pendingReads.reset(unique_fd(dup(ifs->control.pendingReads())));
|
||||
auto logsFd = ifs->control.logs();
|
||||
if (logsFd >= 0) {
|
||||
control.log.reset(unique_fd(dup(logsFd)));
|
||||
}
|
||||
|
||||
std::lock_guard l(mMountOperationLock);
|
||||
const auto status = mVold->setIncFsMountOptions(control, enableReadLogs);
|
||||
if (!status.isOk()) {
|
||||
LOG(ERROR) << "Calling Vold::setIncFsMountOptions() failed: " << status.toString8();
|
||||
return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
|
||||
? status.serviceSpecificErrorCode() > 0 ? -status.serviceSpecificErrorCode()
|
||||
: status.serviceSpecificErrorCode() == 0
|
||||
? -EFAULT
|
||||
: status.serviceSpecificErrorCode()
|
||||
: -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IncrementalService::deleteStorage(StorageId storageId) {
|
||||
const auto ifs = getIfs(storageId);
|
||||
if (!ifs) {
|
||||
@@ -737,10 +767,12 @@ int IncrementalService::makeFile(StorageId storage, std::string_view path, int m
|
||||
if (auto ifs = getIfs(storage)) {
|
||||
std::string normPath = normalizePathToStorage(ifs, storage, path);
|
||||
if (normPath.empty()) {
|
||||
LOG(ERROR) << "Internal error: storageId " << storage << " failed to normalize: " << path;
|
||||
return -EINVAL;
|
||||
}
|
||||
auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params);
|
||||
if (err) {
|
||||
LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile: " << err;
|
||||
return err;
|
||||
}
|
||||
std::vector<uint8_t> metadataBytes;
|
||||
|
||||
@@ -111,6 +111,8 @@ public:
|
||||
int unbind(StorageId storage, std::string_view target);
|
||||
void deleteStorage(StorageId storage);
|
||||
|
||||
int setStorageParams(StorageId storage, bool enableReadLogs);
|
||||
|
||||
int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
|
||||
incfs::NewFileParams params);
|
||||
int makeDir(StorageId storage, std::string_view path, int mode = 0755);
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
|
||||
virtual binder::Status bindMount(const std::string& sourceDir,
|
||||
const std::string& targetDir) const = 0;
|
||||
virtual binder::Status setIncFsMountOptions(const ::android::os::incremental::IncrementalFileSystemControlParcel& control, bool enableReadLogs) const = 0;
|
||||
};
|
||||
|
||||
class DataLoaderManagerWrapper {
|
||||
@@ -106,6 +107,9 @@ public:
|
||||
const std::string& targetDir) const override {
|
||||
return mInterface->bindMount(sourceDir, targetDir);
|
||||
}
|
||||
binder::Status setIncFsMountOptions(const ::android::os::incremental::IncrementalFileSystemControlParcel& control, bool enableReadLogs) const override {
|
||||
return mInterface->setIncFsMountOptions(control, enableReadLogs);
|
||||
}
|
||||
|
||||
private:
|
||||
sp<os::IVold> mInterface;
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
|
||||
MOCK_CONST_METHOD2(bindMount,
|
||||
binder::Status(const std::string& sourceDir, const std::string& argetDir));
|
||||
MOCK_CONST_METHOD2(setIncFsMountOptions,
|
||||
binder::Status(const ::android::os::incremental::IncrementalFileSystemControlParcel&, bool));
|
||||
|
||||
void mountIncFsFails() {
|
||||
ON_CALL(*this, mountIncFs(_, _, _, _))
|
||||
@@ -74,6 +76,14 @@ public:
|
||||
void bindMountSuccess() {
|
||||
ON_CALL(*this, bindMount(_, _)).WillByDefault(Return(binder::Status::ok()));
|
||||
}
|
||||
void setIncFsMountOptionsFails() const {
|
||||
ON_CALL(*this, setIncFsMountOptions(_, _))
|
||||
.WillByDefault(
|
||||
Return(binder::Status::fromExceptionCode(1, String8("failed to set options"))));
|
||||
}
|
||||
void setIncFsMountOptionsSuccess() {
|
||||
ON_CALL(*this, setIncFsMountOptions(_, _)).WillByDefault(Return(binder::Status::ok()));
|
||||
}
|
||||
binder::Status getInvalidControlParcel(const std::string& imagePath,
|
||||
const std::string& targetDir, int32_t flags,
|
||||
IncrementalFileSystemControlParcel* _aidl_return) {
|
||||
@@ -390,6 +400,42 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderSuccess) {
|
||||
ASSERT_TRUE(mIncrementalService->startLoading(storageId));
|
||||
}
|
||||
|
||||
TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) {
|
||||
mVold->mountIncFsSuccess();
|
||||
mIncFs->makeFileSuccess();
|
||||
mVold->bindMountSuccess();
|
||||
mVold->setIncFsMountOptionsSuccess();
|
||||
mDataLoaderManager->initializeDataLoaderSuccess();
|
||||
mDataLoaderManager->getDataLoaderSuccess();
|
||||
EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
|
||||
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
|
||||
EXPECT_CALL(*mVold, setIncFsMountOptions(_, _));
|
||||
TemporaryDir tempDir;
|
||||
int storageId =
|
||||
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
|
||||
IncrementalService::CreateOptions::CreateNew);
|
||||
ASSERT_GE(storageId, 0);
|
||||
ASSERT_GE(mIncrementalService->setStorageParams(storageId, true), 0);
|
||||
}
|
||||
|
||||
TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsFails) {
|
||||
mVold->mountIncFsSuccess();
|
||||
mIncFs->makeFileSuccess();
|
||||
mVold->bindMountSuccess();
|
||||
mVold->setIncFsMountOptionsFails();
|
||||
mDataLoaderManager->initializeDataLoaderSuccess();
|
||||
mDataLoaderManager->getDataLoaderSuccess();
|
||||
EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
|
||||
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
|
||||
EXPECT_CALL(*mVold, setIncFsMountOptions(_, _));
|
||||
TemporaryDir tempDir;
|
||||
int storageId =
|
||||
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
|
||||
IncrementalService::CreateOptions::CreateNew);
|
||||
ASSERT_GE(storageId, 0);
|
||||
ASSERT_LT(mIncrementalService->setStorageParams(storageId, true), 0);
|
||||
}
|
||||
|
||||
TEST_F(IncrementalServiceTest, testMakeDirectory) {
|
||||
mVold->mountIncFsSuccess();
|
||||
mIncFs->makeFileSuccess();
|
||||
|
||||
Reference in New Issue
Block a user