Merge "Disallow read logs collection if user changes their mind." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ab0a32e6ba
@@ -50,6 +50,7 @@ cc_defaults {
|
||||
"libbinder",
|
||||
"libcrypto",
|
||||
"libcutils",
|
||||
"libdataloader",
|
||||
"libincfs",
|
||||
"liblog",
|
||||
"libz",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define LOG_TAG "IncrementalService"
|
||||
|
||||
#include "IncrementalService.h"
|
||||
#include "IncrementalServiceValidation.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
@@ -50,6 +51,9 @@ using namespace std::literals;
|
||||
using namespace android::content::pm;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
constexpr const char* kDataUsageStats = "android.permission.LOADER_USAGE_STATS";
|
||||
constexpr const char* kOpUsage = "android:get_usage_stats";
|
||||
|
||||
namespace android::incremental {
|
||||
|
||||
namespace {
|
||||
@@ -232,6 +236,7 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v
|
||||
: mVold(sm.getVoldService()),
|
||||
mDataLoaderManager(sm.getDataLoaderManager()),
|
||||
mIncFs(sm.getIncFs()),
|
||||
mAppOpsManager(sm.getAppOpsManager()),
|
||||
mIncrementalDir(rootDir) {
|
||||
if (!mVold) {
|
||||
LOG(FATAL) << "Vold service is unavailable";
|
||||
@@ -239,6 +244,9 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v
|
||||
if (!mDataLoaderManager) {
|
||||
LOG(FATAL) << "DataLoaderManagerService is unavailable";
|
||||
}
|
||||
if (!mAppOpsManager) {
|
||||
LOG(FATAL) << "AppOpsManager is unavailable";
|
||||
}
|
||||
mountExistingImages();
|
||||
}
|
||||
|
||||
@@ -279,12 +287,9 @@ void IncrementalService::onDump(int fd) {
|
||||
dprintf(fd, "\t\troot: %s\n", mnt.root.c_str());
|
||||
dprintf(fd, "\t\tnextStorageDirNo: %d\n", mnt.nextStorageDirNo.load());
|
||||
dprintf(fd, "\t\tdataLoaderStatus: %d\n", mnt.dataLoaderStatus.load());
|
||||
dprintf(fd, "\t\tconnectionLostTime: %s\n", toString(mnt.connectionLostTime));
|
||||
dprintf(fd, "\t\tsavedDataLoaderParams:\n");
|
||||
if (!mnt.savedDataLoaderParams) {
|
||||
dprintf(fd, "\t\t\tnone\n");
|
||||
} else {
|
||||
const auto& params = mnt.savedDataLoaderParams.value();
|
||||
{
|
||||
const auto& params = mnt.dataLoaderParams;
|
||||
dprintf(fd, "\t\tdataLoaderParams:\n");
|
||||
dprintf(fd, "\t\t\ttype: %s\n", toString(params.type).c_str());
|
||||
dprintf(fd, "\t\t\tpackageName: %s\n", params.packageName.c_str());
|
||||
dprintf(fd, "\t\t\tclassName: %s\n", params.className.c_str());
|
||||
@@ -332,6 +337,7 @@ std::optional<std::future<void>> IncrementalService::onSystemReady() {
|
||||
}
|
||||
|
||||
std::thread([this, mounts = std::move(mounts)]() {
|
||||
/* TODO(b/151241369): restore data loaders on reboot.
|
||||
for (auto&& ifs : mounts) {
|
||||
if (prepareDataLoader(*ifs)) {
|
||||
LOG(INFO) << "Successfully started data loader for mount " << ifs->mountId;
|
||||
@@ -340,6 +346,7 @@ std::optional<std::future<void>> IncrementalService::onSystemReady() {
|
||||
LOG(WARNING) << "Failed to start data loader for mount " << ifs->mountId;
|
||||
}
|
||||
}
|
||||
*/
|
||||
mPrepareDataLoaders.set_value_at_thread_exit();
|
||||
}).detach();
|
||||
return mPrepareDataLoaders.get_future();
|
||||
@@ -459,13 +466,15 @@ StorageId IncrementalService::createStorage(
|
||||
return kInvalidStorageId;
|
||||
}
|
||||
|
||||
ifs->dataLoaderParams = std::move(dataLoaderParams);
|
||||
|
||||
{
|
||||
metadata::Mount m;
|
||||
m.mutable_storage()->set_id(ifs->mountId);
|
||||
m.mutable_loader()->set_type((int)dataLoaderParams.type);
|
||||
m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
|
||||
m.mutable_loader()->set_class_name(dataLoaderParams.className);
|
||||
m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
|
||||
m.mutable_loader()->set_type((int)ifs->dataLoaderParams.type);
|
||||
m.mutable_loader()->set_package_name(ifs->dataLoaderParams.packageName);
|
||||
m.mutable_loader()->set_class_name(ifs->dataLoaderParams.className);
|
||||
m.mutable_loader()->set_arguments(ifs->dataLoaderParams.arguments);
|
||||
const auto metadata = m.SerializeAsString();
|
||||
m.mutable_loader()->release_arguments();
|
||||
m.mutable_loader()->release_class_name();
|
||||
@@ -493,7 +502,7 @@ StorageId IncrementalService::createStorage(
|
||||
// Done here as well, all data structures are in good state.
|
||||
secondCleanupOnFailure.release();
|
||||
|
||||
if (!prepareDataLoader(*ifs, &dataLoaderParams, &dataLoaderStatusListener)) {
|
||||
if (!prepareDataLoader(*ifs, &dataLoaderStatusListener)) {
|
||||
LOG(ERROR) << "prepareDataLoader() failed";
|
||||
deleteStorageLocked(*ifs, std::move(l));
|
||||
return kInvalidStorageId;
|
||||
@@ -573,11 +582,30 @@ int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLog
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ifs->dataLoaderFilesystemParams.readLogsEnabled = enableReadLogs;
|
||||
if (enableReadLogs) {
|
||||
// We never unregister the callbacks, but given a restricted number of data loaders and even fewer asking for read log access, should be ok.
|
||||
registerAppOpsCallback(ifs->dataLoaderParams.packageName);
|
||||
}
|
||||
|
||||
return applyStorageParams(*ifs);
|
||||
}
|
||||
|
||||
int IncrementalService::applyStorageParams(IncFsMount& ifs) {
|
||||
const bool enableReadLogs = ifs.dataLoaderFilesystemParams.readLogsEnabled;
|
||||
if (enableReadLogs) {
|
||||
if (auto status = CheckPermissionForDataDelivery(kDataUsageStats, kOpUsage);
|
||||
!status.isOk()) {
|
||||
LOG(ERROR) << "CheckPermissionForDataDelivery failed: " << status.toString8();
|
||||
return fromBinderStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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)));
|
||||
}
|
||||
@@ -586,12 +614,7 @@ int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLog
|
||||
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 fromBinderStatus(status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1015,16 +1038,26 @@ bool IncrementalService::mountExistingImage(std::string_view root) {
|
||||
|
||||
auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
|
||||
|
||||
auto m = parseFromIncfs<metadata::Mount>(mIncFs.get(), ifs->control,
|
||||
path::join(mountTarget, constants().infoMdName));
|
||||
if (!m.has_loader() || !m.has_storage()) {
|
||||
auto mount = parseFromIncfs<metadata::Mount>(mIncFs.get(), ifs->control,
|
||||
path::join(mountTarget, constants().infoMdName));
|
||||
if (!mount.has_loader() || !mount.has_storage()) {
|
||||
LOG(ERROR) << "Bad mount metadata in mount at " << root;
|
||||
return false;
|
||||
}
|
||||
|
||||
ifs->mountId = m.storage().id();
|
||||
ifs->mountId = mount.storage().id();
|
||||
mNextId = std::max(mNextId, ifs->mountId + 1);
|
||||
|
||||
// DataLoader params
|
||||
{
|
||||
auto& dlp = ifs->dataLoaderParams;
|
||||
const auto& loader = mount.loader();
|
||||
dlp.type = (android::content::pm::DataLoaderType)loader.type();
|
||||
dlp.packageName = loader.package_name();
|
||||
dlp.className = loader.class_name();
|
||||
dlp.arguments = loader.arguments();
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
|
||||
auto d = openDir(path::c_str(mountTarget));
|
||||
while (auto e = ::readdir(d.get())) {
|
||||
@@ -1095,23 +1128,9 @@ bool IncrementalService::mountExistingImage(std::string_view root) {
|
||||
}
|
||||
|
||||
bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
|
||||
DataLoaderParamsParcel* params,
|
||||
const DataLoaderStatusListener* externalListener) {
|
||||
if (!mSystemReady.load(std::memory_order_relaxed)) {
|
||||
std::unique_lock l(ifs.lock);
|
||||
if (params) {
|
||||
if (ifs.savedDataLoaderParams) {
|
||||
LOG(WARNING) << "Trying to pass second set of data loader parameters, ignored it";
|
||||
} else {
|
||||
ifs.savedDataLoaderParams = std::move(*params);
|
||||
}
|
||||
} else {
|
||||
if (!ifs.savedDataLoaderParams) {
|
||||
LOG(ERROR) << "Mount " << ifs.mountId
|
||||
<< " is broken: no data loader params (system is not ready yet)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true; // eventually...
|
||||
}
|
||||
|
||||
@@ -1121,12 +1140,6 @@ bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* dlp = params ? params
|
||||
: ifs.savedDataLoaderParams ? &ifs.savedDataLoaderParams.value() : nullptr;
|
||||
if (!dlp) {
|
||||
LOG(ERROR) << "Mount " << ifs.mountId << " is broken: no data loader params";
|
||||
return false;
|
||||
}
|
||||
FileSystemControlParcel fsControlParcel;
|
||||
fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
|
||||
fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd())));
|
||||
@@ -1138,13 +1151,11 @@ bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
|
||||
externalListener ? *externalListener
|
||||
: DataLoaderStatusListener());
|
||||
bool created = false;
|
||||
auto status = mDataLoaderManager->initializeDataLoader(ifs.mountId, *dlp, fsControlParcel,
|
||||
listener, &created);
|
||||
auto status = mDataLoaderManager->initializeDataLoader(ifs.mountId, ifs.dataLoaderParams, fsControlParcel, listener, &created);
|
||||
if (!status.isOk() || !created) {
|
||||
LOG(ERROR) << "Failed to create a data loader for mount " << ifs.mountId;
|
||||
return false;
|
||||
}
|
||||
ifs.savedDataLoaderParams.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1268,6 +1279,42 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
|
||||
return success;
|
||||
}
|
||||
|
||||
void IncrementalService::registerAppOpsCallback(const std::string& packageName) {
|
||||
if (packageName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock lock{mCallbacksLock};
|
||||
if (!mCallbackRegistered.insert(packageName).second) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(b/152633648): restore callback after it's not crashing Binder anymore.
|
||||
sp<AppOpsListener> listener = new AppOpsListener(*this, packageName);
|
||||
mAppOpsManager->startWatchingMode(AppOpsManager::OP_GET_USAGE_STATS, String16(packageName.c_str()), listener);
|
||||
*/
|
||||
}
|
||||
|
||||
void IncrementalService::onAppOppChanged(const std::string& packageName) {
|
||||
std::vector<IfsMountPtr> affected;
|
||||
{
|
||||
std::lock_guard l(mLock);
|
||||
affected.reserve(mMounts.size());
|
||||
for (auto&& [id, ifs] : mMounts) {
|
||||
if (ifs->dataLoaderFilesystemParams.readLogsEnabled && ifs->dataLoaderParams.packageName == packageName) {
|
||||
affected.push_back(ifs);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO(b/152633648): restore callback after it's not crashing Kernel anymore.
|
||||
for (auto&& ifs : affected) {
|
||||
applyStorageParams(*ifs);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChanged(MountId mountId,
|
||||
int newStatus) {
|
||||
if (externalListener) {
|
||||
@@ -1331,4 +1378,8 @@ binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChange
|
||||
return binder::Status::ok();
|
||||
}
|
||||
|
||||
void IncrementalService::AppOpsListener::opChanged(int32_t op, const String16&) {
|
||||
incrementalService.onAppOppChanged(packageName);
|
||||
}
|
||||
|
||||
} // namespace android::incremental
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "ServiceWrappers.h"
|
||||
#include "android/content/pm/BnDataLoaderStatusListener.h"
|
||||
#include "incfs.h"
|
||||
#include "dataloader_ndk.h"
|
||||
#include "path.h"
|
||||
|
||||
using namespace android::os::incremental;
|
||||
@@ -132,6 +133,7 @@ public:
|
||||
bool startLoading(StorageId storage) const;
|
||||
bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
|
||||
std::string_view libDirRelativePath, std::string_view abi);
|
||||
|
||||
class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
|
||||
public:
|
||||
IncrementalDataLoaderListener(IncrementalService& incrementalService,
|
||||
@@ -145,6 +147,16 @@ public:
|
||||
DataLoaderStatusListener externalListener;
|
||||
};
|
||||
|
||||
class AppOpsListener : public android::BnAppOpsCallback {
|
||||
public:
|
||||
AppOpsListener(IncrementalService& incrementalService, std::string packageName) : incrementalService(incrementalService), packageName(std::move(packageName)) {}
|
||||
void opChanged(int32_t op, const String16& packageName) override;
|
||||
|
||||
private:
|
||||
IncrementalService& incrementalService;
|
||||
const std::string packageName;
|
||||
};
|
||||
|
||||
private:
|
||||
struct IncFsMount {
|
||||
struct Bind {
|
||||
@@ -169,11 +181,11 @@ private:
|
||||
/*const*/ MountId mountId;
|
||||
StorageMap storages;
|
||||
BindMap bindPoints;
|
||||
std::optional<DataLoaderParamsParcel> savedDataLoaderParams;
|
||||
DataLoaderParamsParcel dataLoaderParams;
|
||||
DataLoaderFilesystemParams dataLoaderFilesystemParams;
|
||||
std::atomic<int> nextStorageDirNo{0};
|
||||
std::atomic<int> dataLoaderStatus = -1;
|
||||
bool dataLoaderStartRequested = false;
|
||||
TimePoint connectionLostTime = TimePoint();
|
||||
const IncrementalService& incrementalService;
|
||||
|
||||
IncFsMount(std::string root, MountId mountId, Control control,
|
||||
@@ -181,7 +193,9 @@ private:
|
||||
: root(std::move(root)),
|
||||
control(std::move(control)),
|
||||
mountId(mountId),
|
||||
incrementalService(incrementalService) {}
|
||||
incrementalService(incrementalService) {
|
||||
dataLoaderFilesystemParams.readLogsEnabled = false;
|
||||
}
|
||||
IncFsMount(IncFsMount&&) = delete;
|
||||
IncFsMount& operator=(IncFsMount&&) = delete;
|
||||
~IncFsMount();
|
||||
@@ -208,8 +222,7 @@ private:
|
||||
std::string&& source, std::string&& target, BindKind kind,
|
||||
std::unique_lock<std::mutex>& mainLock);
|
||||
|
||||
bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params = nullptr,
|
||||
const DataLoaderStatusListener* externalListener = nullptr);
|
||||
bool prepareDataLoader(IncFsMount& ifs, const DataLoaderStatusListener* externalListener = nullptr);
|
||||
bool startDataLoader(MountId mountId) const;
|
||||
|
||||
BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
|
||||
@@ -221,10 +234,16 @@ private:
|
||||
std::string normalizePathToStorage(const IfsMountPtr incfs, StorageId storage,
|
||||
std::string_view path);
|
||||
|
||||
int applyStorageParams(IncFsMount& ifs);
|
||||
|
||||
void registerAppOpsCallback(const std::string& packageName);
|
||||
void onAppOppChanged(const std::string& packageName);
|
||||
|
||||
// Member variables
|
||||
std::unique_ptr<VoldServiceWrapper> mVold;
|
||||
std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
|
||||
std::unique_ptr<IncFsWrapper> mIncFs;
|
||||
std::unique_ptr<VoldServiceWrapper> const mVold;
|
||||
std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
|
||||
std::unique_ptr<IncFsWrapper> const mIncFs;
|
||||
std::unique_ptr<AppOpsManagerWrapper> const mAppOpsManager;
|
||||
const std::string mIncrementalDir;
|
||||
|
||||
mutable std::mutex mLock;
|
||||
@@ -232,6 +251,9 @@ private:
|
||||
MountMap mMounts;
|
||||
BindPathMap mBindsByPath;
|
||||
|
||||
std::mutex mCallbacksLock;
|
||||
std::set<std::string> mCallbackRegistered;
|
||||
|
||||
std::atomic_bool mSystemReady = false;
|
||||
StorageId mNextId = 0;
|
||||
std::promise<void> mPrepareDataLoaders;
|
||||
|
||||
75
services/incremental/IncrementalServiceValidation.h
Normal file
75
services/incremental/IncrementalServiceValidation.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/PermissionCache.h>
|
||||
#include <binder/PermissionController.h>
|
||||
#include <binder/Status.h>
|
||||
|
||||
namespace android::incremental {
|
||||
|
||||
inline binder::Status Ok() {
|
||||
return binder::Status::ok();
|
||||
}
|
||||
|
||||
inline binder::Status Exception(uint32_t code, const std::string& msg) {
|
||||
return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
|
||||
}
|
||||
|
||||
inline int fromBinderStatus(const binder::Status& status) {
|
||||
return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
|
||||
? status.serviceSpecificErrorCode() > 0 ? -status.serviceSpecificErrorCode()
|
||||
: status.serviceSpecificErrorCode() == 0
|
||||
? -EFAULT
|
||||
: status.serviceSpecificErrorCode()
|
||||
: -EIO;
|
||||
}
|
||||
|
||||
inline binder::Status CheckPermissionForDataDelivery(const char* permission, const char* operation) {
|
||||
using android::base::StringPrintf;
|
||||
|
||||
int32_t pid;
|
||||
int32_t uid;
|
||||
|
||||
if (!PermissionCache::checkCallingPermission(String16(permission), &pid, &uid)) {
|
||||
return Exception(binder::Status::EX_SECURITY,
|
||||
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
|
||||
}
|
||||
|
||||
// Caller must also have op granted.
|
||||
PermissionController pc;
|
||||
// Package is a required parameter. Need to obtain one.
|
||||
Vector<String16> packages;
|
||||
pc.getPackagesForUid(uid, packages);
|
||||
if (packages.empty()) {
|
||||
return Exception(binder::Status::EX_SECURITY,
|
||||
StringPrintf("UID %d / PID %d has no packages", uid, pid));
|
||||
}
|
||||
switch (auto result = pc.noteOp(String16(operation), uid, packages[0]); result) {
|
||||
case PermissionController::MODE_ALLOWED:
|
||||
case PermissionController::MODE_DEFAULT:
|
||||
return binder::Status::ok();
|
||||
default:
|
||||
return Exception(binder::Status::EX_SECURITY,
|
||||
StringPrintf("UID %d / PID %d lacks app-op %s, error %d", uid, pid,
|
||||
operation, result));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android::incremental
|
||||
@@ -59,4 +59,8 @@ std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
|
||||
return std::make_unique<RealIncFs>();
|
||||
}
|
||||
|
||||
std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
|
||||
return std::make_unique<RealAppOpsManager>();
|
||||
}
|
||||
|
||||
} // namespace android::os::incremental
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <android/content/pm/IDataLoaderManager.h>
|
||||
#include <android/content/pm/IDataLoaderStatusListener.h>
|
||||
#include <android/os/IVold.h>
|
||||
#include <binder/AppOpsManager.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <incfs.h>
|
||||
|
||||
@@ -81,12 +82,19 @@ public:
|
||||
virtual ErrorCode writeBlocks(Span<const DataBlock> blocks) const = 0;
|
||||
};
|
||||
|
||||
class AppOpsManagerWrapper {
|
||||
public:
|
||||
virtual ~AppOpsManagerWrapper() = default;
|
||||
virtual void startWatchingMode(int32_t op, const String16& packageName, const sp<IAppOpsCallback>& callback) = 0;
|
||||
};
|
||||
|
||||
class ServiceManagerWrapper {
|
||||
public:
|
||||
virtual ~ServiceManagerWrapper() = default;
|
||||
virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
|
||||
virtual std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() = 0;
|
||||
virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
|
||||
virtual std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() = 0;
|
||||
};
|
||||
|
||||
// --- Real stuff ---
|
||||
@@ -137,13 +145,24 @@ private:
|
||||
sp<content::pm::IDataLoaderManager> mInterface;
|
||||
};
|
||||
|
||||
class RealAppOpsManager : public AppOpsManagerWrapper {
|
||||
public:
|
||||
~RealAppOpsManager() = default;
|
||||
void startWatchingMode(int32_t op, const String16& packageName, const sp<IAppOpsCallback>& callback) override {
|
||||
mAppOpsManager.startWatchingMode(op, packageName, callback);
|
||||
}
|
||||
private:
|
||||
android::AppOpsManager mAppOpsManager;
|
||||
};
|
||||
|
||||
class RealServiceManager : public ServiceManagerWrapper {
|
||||
public:
|
||||
RealServiceManager(sp<IServiceManager> serviceManager);
|
||||
~RealServiceManager() = default;
|
||||
std::unique_ptr<VoldServiceWrapper> getVoldService() override;
|
||||
std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() override;
|
||||
std::unique_ptr<IncFsWrapper> getIncFs() override;
|
||||
std::unique_ptr<VoldServiceWrapper> getVoldService() final;
|
||||
std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final;
|
||||
std::unique_ptr<IncFsWrapper> getIncFs() final;
|
||||
std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final;
|
||||
|
||||
private:
|
||||
template <class INTERFACE>
|
||||
|
||||
@@ -220,24 +220,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MockAppOpsManager : public AppOpsManagerWrapper {
|
||||
MOCK_METHOD3(startWatchingMode, void(int32_t, const String16&, const sp<IAppOpsCallback>&));
|
||||
};
|
||||
|
||||
class MockServiceManager : public ServiceManagerWrapper {
|
||||
public:
|
||||
MockServiceManager(std::unique_ptr<MockVoldService> vold,
|
||||
std::unique_ptr<MockDataLoaderManager> manager,
|
||||
std::unique_ptr<MockIncFs> incfs)
|
||||
std::unique_ptr<MockIncFs> incfs,
|
||||
std::unique_ptr<MockAppOpsManager> appOpsManager)
|
||||
: mVold(std::move(vold)),
|
||||
mDataLoaderManager(std::move(manager)),
|
||||
mIncFs(std::move(incfs)) {}
|
||||
mIncFs(std::move(incfs)),
|
||||
mAppOpsManager(std::move(appOpsManager)) {}
|
||||
std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
|
||||
std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final {
|
||||
return std::move(mDataLoaderManager);
|
||||
}
|
||||
std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
|
||||
std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final { return std::move(mAppOpsManager); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<MockVoldService> mVold;
|
||||
std::unique_ptr<MockDataLoaderManager> mDataLoaderManager;
|
||||
std::unique_ptr<MockIncFs> mIncFs;
|
||||
std::unique_ptr<MockAppOpsManager> mAppOpsManager;
|
||||
};
|
||||
|
||||
// --- IncrementalServiceTest ---
|
||||
@@ -251,11 +259,13 @@ public:
|
||||
mDataLoaderManager = dataloaderManager.get();
|
||||
auto incFs = std::make_unique<NiceMock<MockIncFs>>();
|
||||
mIncFs = incFs.get();
|
||||
auto appOps = std::make_unique<NiceMock<MockAppOpsManager>>();
|
||||
mAppOpsManager = appOps.get();
|
||||
mIncrementalService =
|
||||
std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
|
||||
std::move(
|
||||
dataloaderManager),
|
||||
std::move(incFs)),
|
||||
std::move(dataloaderManager),
|
||||
std::move(incFs),
|
||||
std::move(appOps)),
|
||||
mRootDir.path);
|
||||
mDataLoaderParcel.packageName = "com.test";
|
||||
mDataLoaderParcel.arguments = "uri";
|
||||
@@ -287,6 +297,7 @@ protected:
|
||||
NiceMock<MockVoldService>* mVold;
|
||||
NiceMock<MockIncFs>* mIncFs;
|
||||
NiceMock<MockDataLoaderManager>* mDataLoaderManager;
|
||||
NiceMock<MockAppOpsManager>* mAppOpsManager;
|
||||
std::unique_ptr<IncrementalService> mIncrementalService;
|
||||
TemporaryDir mRootDir;
|
||||
DataLoaderParamsParcel mDataLoaderParcel;
|
||||
|
||||
Reference in New Issue
Block a user