Files
frameworks_base/services/incremental/BinderIncrementalService.cpp
Songchun Fan 2570ec01c6 [incremental/pm] set health listener on commit and on reboot
This changes allow Incremental Service to directly report health status
to package manager service.

A health listener is created during package installation session to
monitor incremental storage health. After commit, a new listener is
created and will overwrite the old one.

The new listener will listen to incremental storage health and report
the status to package manager service, which will then send the status
to IncrementalStates, where the startability state and unstartable
reason might change, based on the health status code.

During reboot, for each incremental package, if it is not fully loaded,
the package manager service will register a health status listener to
continue monitor the health status of this package.

Test: unit test
Test: manual
BUG: 170435166
Change-Id: I220f230c523cfaf2c96019f9478554665e6af486
2020-10-20 01:13:07 +00:00

359 lines
14 KiB
C++

/*
* Copyright (C) 2019 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.
*/
#include "BinderIncrementalService.h"
#include <android-base/logging.h>
#include <android-base/no_destructor.h>
#include <android/os/IVold.h>
#include <binder/IResultReceiver.h>
#include <binder/PermissionCache.h>
#include <incfs.h>
#include "ServiceWrappers.h"
#include "jni.h"
#include "path.h"
using namespace std::literals;
using namespace android::incremental;
namespace android::os::incremental {
static constexpr auto kAndroidDataEnv = "ANDROID_DATA"sv;
static constexpr auto kDataDir = "/data"sv;
static constexpr auto kIncrementalSubDir = "incremental"sv;
static std::string getIncrementalDir() {
const char* dataDir = getenv(kAndroidDataEnv.data());
if (!dataDir || !*dataDir) {
dataDir = kDataDir.data();
}
return path::normalize(path::join(dataDir, kIncrementalSubDir));
}
static bool incFsEnabled() {
// TODO(b/136132412): use vold to check /sys/fs/incfs/version (per selinux compliance)
return incfs::enabled();
}
static bool incFsValid(const sp<IVold>& vold) {
bool enabled = false;
auto status = vold->incFsEnabled(&enabled);
if (!status.isOk() || !enabled) {
return false;
}
return true;
}
BinderIncrementalService::BinderIncrementalService(const sp<IServiceManager>& sm, JNIEnv* env)
: mImpl(RealServiceManager(sm, env), getIncrementalDir()) {}
BinderIncrementalService* BinderIncrementalService::start(JNIEnv* env) {
if (!incFsEnabled()) {
return nullptr;
}
IPCThreadState::self()->disableBackgroundScheduling(true);
sp<IServiceManager> sm(defaultServiceManager());
if (!sm) {
return nullptr;
}
sp<IBinder> voldBinder(sm->getService(String16("vold")));
if (voldBinder == nullptr) {
return nullptr;
}
sp<IVold> vold = interface_cast<IVold>(voldBinder);
if (!incFsValid(vold)) {
return nullptr;
}
sp<BinderIncrementalService> self(new BinderIncrementalService(sm, env));
status_t ret = sm->addService(String16{getServiceName()}, self);
if (ret != android::OK) {
return nullptr;
}
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
// sm->addService increments the reference count, and now we're OK with returning the pointer.
return self.get();
}
status_t BinderIncrementalService::dump(int fd, const Vector<String16>&) {
static const android::base::NoDestructor<String16> kDump("android.permission.DUMP");
if (!PermissionCache::checkCallingPermission(*kDump)) {
return PERMISSION_DENIED;
}
mImpl.onDump(fd);
return NO_ERROR;
}
void BinderIncrementalService::onSystemReady() {
mImpl.onSystemReady();
}
static binder::Status ok() {
return binder::Status::ok();
}
binder::Status BinderIncrementalService::openStorage(const std::string& path,
int32_t* _aidl_return) {
*_aidl_return = mImpl.openStorage(path);
return ok();
}
binder::Status BinderIncrementalService::createStorage(
const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
int32_t createMode,
const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
const ::android::sp<::android::os::incremental::IStorageHealthListener>& healthListener,
int32_t* _aidl_return) {
*_aidl_return =
mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
android::incremental::IncrementalService::CreateOptions(createMode),
statusListener,
const_cast<StorageHealthCheckParams&&>(healthCheckParams),
healthListener);
return ok();
}
binder::Status BinderIncrementalService::createLinkedStorage(const std::string& path,
int32_t otherStorageId,
int32_t createMode,
int32_t* _aidl_return) {
*_aidl_return =
mImpl.createLinkedStorage(path, otherStorageId,
android::incremental::IncrementalService::CreateOptions(
createMode));
return ok();
}
binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
const std::string& sourcePath,
const std::string& targetFullPath,
int32_t bindType, int32_t* _aidl_return) {
*_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
android::incremental::IncrementalService::BindKind(bindType));
return ok();
}
binder::Status BinderIncrementalService::deleteBindMount(int32_t storageId,
const std::string& targetFullPath,
int32_t* _aidl_return) {
*_aidl_return = mImpl.unbind(storageId, targetFullPath);
return ok();
}
binder::Status BinderIncrementalService::deleteStorage(int32_t storageId) {
mImpl.deleteStorage(storageId);
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,
int32_t* _aidl_return) {
*_aidl_return = mImpl.makeDir(storageId, path);
return ok();
}
static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
const android::os::incremental::IncrementalNewFileParams& params) {
incfs::FileId id;
if (params.fileId.empty()) {
if (params.metadata.empty()) {
return {EINVAL, {}, {}};
}
id = IncrementalService::idFromMetadata(params.metadata);
} else if (params.fileId.size() != sizeof(id)) {
return {EINVAL, {}, {}};
} else {
memcpy(&id, params.fileId.data(), sizeof(id));
}
incfs::NewFileParams nfp;
nfp.size = params.size;
nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
if (!params.signature) {
nfp.signature = {};
} else {
nfp.signature = {(const char*)params.signature->data(),
(IncFsSize)params.signature->size()};
}
return {0, id, nfp};
}
static std::span<const uint8_t> toSpan(const ::std::optional<::std::vector<uint8_t>>& content) {
if (!content) {
return {};
}
return {content->data(), (int)content->size()};
}
binder::Status BinderIncrementalService::makeFile(
int32_t storageId, const std::string& path,
const ::android::os::incremental::IncrementalNewFileParams& params,
const ::std::optional<::std::vector<uint8_t>>& content, int32_t* _aidl_return) {
auto [err, fileId, nfp] = toMakeFileParams(params);
if (err) {
*_aidl_return = err;
return ok();
}
*_aidl_return = mImpl.makeFile(storageId, path, 0777, fileId, nfp, toSpan(content));
return ok();
}
binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
const std::string& targetPath,
const std::string& sourcePath,
int64_t start, int64_t end,
int32_t* _aidl_return) {
// TODO(b/136132412): implement this
*_aidl_return = ENOSYS; // not implemented
return ok();
}
binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
const std::string& sourcePath,
int32_t destStorageId,
const std::string& destPath,
int32_t* _aidl_return) {
*_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
return ok();
}
binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
int32_t* _aidl_return) {
*_aidl_return = mImpl.unlink(storageId, path);
return ok();
}
binder::Status BinderIncrementalService::isFileFullyLoaded(int32_t storageId,
const std::string& path,
int32_t* _aidl_return) {
*_aidl_return = mImpl.isFileFullyLoaded(storageId, path);
return ok();
}
binder::Status BinderIncrementalService::getLoadingProgress(int32_t storageId,
float* _aidl_return) {
*_aidl_return = mImpl.getLoadingProgress(storageId);
return ok();
}
binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
const std::string& path,
std::vector<uint8_t>* _aidl_return) {
auto metadata = mImpl.getMetadata(storageId, path);
_aidl_return->assign(metadata.begin(), metadata.end());
return ok();
}
static FileId toFileId(const std::vector<uint8_t>& id) {
FileId fid;
memcpy(&fid, id.data(), id.size());
return fid;
}
binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
const std::vector<uint8_t>& id,
std::vector<uint8_t>* _aidl_return) {
if (id.size() != sizeof(incfs::FileId)) {
return ok();
}
auto fid = toFileId(id);
auto metadata = mImpl.getMetadata(storageId, fid);
_aidl_return->assign(metadata.begin(), metadata.end());
return ok();
}
binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
int32_t* _aidl_return) {
*_aidl_return = mImpl.makeDirs(storageId, path);
return ok();
}
binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
*_aidl_return = mImpl.startLoading(storageId);
return ok();
}
binder::Status BinderIncrementalService::configureNativeBinaries(
int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath,
const std::string& abi, bool extractNativeLibs, bool* _aidl_return) {
*_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi,
extractNativeLibs);
return ok();
}
binder::Status BinderIncrementalService::waitForNativeBinariesExtraction(int storageId,
bool* _aidl_return) {
*_aidl_return = mImpl.waitForNativeBinariesExtraction(storageId);
return ok();
}
binder::Status BinderIncrementalService::registerLoadingProgressListener(
int32_t storageId,
const ::android::sp<::android::os::incremental::IStorageLoadingProgressListener>&
progressListener,
bool* _aidl_return) {
*_aidl_return = mImpl.registerLoadingProgressListener(storageId, progressListener);
return ok();
}
binder::Status BinderIncrementalService::unregisterLoadingProgressListener(int32_t storageId,
bool* _aidl_return) {
*_aidl_return = mImpl.unregisterLoadingProgressListener(storageId);
return ok();
}
binder::Status BinderIncrementalService::registerStorageHealthListener(
int32_t storageId,
const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) {
*_aidl_return = mImpl.registerStorageHealthListener(storageId,
const_cast<StorageHealthCheckParams&&>(
healthCheckParams),
healthListener);
return ok();
}
binder::Status BinderIncrementalService::unregisterStorageHealthListener(int32_t storageId) {
mImpl.unregisterStorageHealthListener(storageId);
return ok();
}
} // namespace android::os::incremental
jlong Incremental_IncrementalService_Start(JNIEnv* env) {
return (jlong)android::os::incremental::BinderIncrementalService::start(env);
}
void Incremental_IncrementalService_OnSystemReady(jlong self) {
if (self) {
((android::os::incremental::BinderIncrementalService*)self)->onSystemReady();
}
}
void Incremental_IncrementalService_OnDump(jlong self, jint fd) {
if (self) {
((android::os::incremental::BinderIncrementalService*)self)->dump(fd, {});
} else {
dprintf(fd, "BinderIncrementalService is stopped.");
}
}