From f63f6011fa77e588e96c0c674b06f6d86ae06f8a Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Tue, 28 Feb 2023 15:41:12 +0900 Subject: [PATCH] Adding ApexInfo utility This is to get name/version when the HAL is started from an APEX. This is the initial work and just prints name/version on startup. Bug: 268439003 Test: adb logcat | grep com.google.android.widevine Change-Id: I756c042d544f973999738f7d17022d916b9712cd --- libwvdrmengine/Android.bp | 8 +- libwvdrmengine/apex/Android.bp | 5 ++ libwvdrmengine/apex/file_contexts | 8 +- libwvdrmengine/apex/proto/Android.bp | 42 +++++++++++ .../apex/proto/apex_manifest_minimal.proto | 31 ++++++++ .../apex/proto/widevine_apex_info.cpp | 75 +++++++++++++++++++ .../apex/proto/widevine_apex_info.h | 34 +++++++++ libwvdrmengine/src/service.cpp | 8 ++ 8 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 libwvdrmengine/apex/proto/Android.bp create mode 100644 libwvdrmengine/apex/proto/apex_manifest_minimal.proto create mode 100644 libwvdrmengine/apex/proto/widevine_apex_info.cpp create mode 100644 libwvdrmengine/apex/proto/widevine_apex_info.h diff --git a/libwvdrmengine/Android.bp b/libwvdrmengine/Android.bp index 8198364c..29ad5003 100644 --- a/libwvdrmengine/Android.bp +++ b/libwvdrmengine/Android.bp @@ -129,7 +129,13 @@ cc_binary { "frameworks/native/libs/binder/include", ], - shared_libs: ["libbinder_ndk"], + shared_libs: [ + "libbinder_ndk", + "libprotobuf-cpp-lite", + ], + static_libs: [ + "lib_apex_manifest_minimal_proto_lite", + ], init_rc: ["src/android.hardware.drm-service.widevine.rc"], vintf_fragments: ["manifest_android.hardware.drm-service.widevine.xml"], diff --git a/libwvdrmengine/apex/Android.bp b/libwvdrmengine/apex/Android.bp index 35173df5..5fc78098 100644 --- a/libwvdrmengine/apex/Android.bp +++ b/libwvdrmengine/apex/Android.bp @@ -74,6 +74,11 @@ apex { ], binaries: ["android.hardware.drm-service.widevine"], file_contexts: "file_contexts", + // TODO(b/268439003) We need an API to get apex version. Until then + // we'll read apex_manifest.pb to get the version. To label apex_manifest.pb + // as vendor_configs_file (which the apex can access), turn off force-label. + use_file_contexts_as_is: true, + use_vndk_as_stable: true, updatable: false, diff --git a/libwvdrmengine/apex/file_contexts b/libwvdrmengine/apex/file_contexts index 4a6b094a..ea029e07 100644 --- a/libwvdrmengine/apex/file_contexts +++ b/libwvdrmengine/apex/file_contexts @@ -1,3 +1,9 @@ (/.*)? u:object_r:vendor_file:s0 /bin/hw/android\.hardware\.drm-service\.widevine u:object_r:hal_drm_widevine_exec:s0 -/etc(/.*)? u:object_r:vendor_configs_file:s0 \ No newline at end of file +/etc(/.*)? u:object_r:vendor_configs_file:s0 +# TODO(b/268439003) Following two entries are typically handled by the build system. +# We override it so that the Widevine APEX can access it to get the apex version. +# When we have a proper API, we can delete these along with +# use_file_contexts_as_is property in Android.bp +/apex_manifest\.pb u:object_r:vendor_configs_file:s0 +/ u:object_r:system_file:s0 \ No newline at end of file diff --git a/libwvdrmengine/apex/proto/Android.bp b/libwvdrmengine/apex/proto/Android.bp new file mode 100644 index 00000000..39bb0473 --- /dev/null +++ b/libwvdrmengine/apex/proto/Android.bp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 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. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +// TODO(b/268439003) The widevine apex wants to get the apex version. +// Since there's no such API, we read it from apex_manifest.pb directly via +// a partial view proto. +// When we have a proper API, we can delete this proto because it should be +// internal to system. +cc_library_static { + name: "lib_apex_manifest_minimal_proto_lite", + proto: { + type: "lite", + }, + export_include_dirs: [ + ".", + ], + srcs: [ + "apex_manifest_minimal.proto", + "widevine_apex_info.cpp", + ], + shared_libs: [ + "libbase", + ], + vendor: true, +} diff --git a/libwvdrmengine/apex/proto/apex_manifest_minimal.proto b/libwvdrmengine/apex/proto/apex_manifest_minimal.proto new file mode 100644 index 00000000..37a93703 --- /dev/null +++ b/libwvdrmengine/apex/proto/apex_manifest_minimal.proto @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 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. + */ + +syntax = "proto3"; + +package apex.proto; + +// This is a partial view for system/apex/proto/apex_manifest.proto. +message ApexManifest { + + // APEX Name. Note that this can be different from what PackageManager sees. + // This is used to identify an APEX and to mount under /apex directory. + string name = 1; + + // Version Number + int64 version = 2; + +} \ No newline at end of file diff --git a/libwvdrmengine/apex/proto/widevine_apex_info.cpp b/libwvdrmengine/apex/proto/widevine_apex_info.cpp new file mode 100644 index 00000000..0e317a64 --- /dev/null +++ b/libwvdrmengine/apex/proto/widevine_apex_info.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2023 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 "widevine_apex_info.h" + +#include +#include + +#include "apex_manifest_minimal.pb.h" + +using android::base::ConsumePrefix; +using android::base::ErrnoError; +using android::base::Error; +using android::base::GetExecutablePath; +using android::base::ReadFileToString; +using android::base::Result; +using apex::proto::ApexManifest; + +namespace widevine::apex { + +namespace { + +Result GetApexNameFromPath(const std::string& path) { + std::string_view sv{path}; + if (!ConsumePrefix(&sv, "/apex/")) { + return Error() << "Not found an apex name: " << path; + } + return std::string{sv.substr(0, sv.find('/'))}; +} + +Result ParseApexManifest(const std::string& manifest_path) { + std::string content; + if (!ReadFileToString(manifest_path, &content)) { + return ErrnoError() << "Failed to read manifest file: " << manifest_path; + } + ApexManifest manifest; + if (!manifest.ParseFromString(content)) { + return Error() << "Can't parse APEX manifest: " << manifest_path; + } + return manifest; +} + +} + +Result GetApexInfo() { + auto exe_path = GetExecutablePath(); + auto apex_name = GetApexNameFromPath(exe_path); + if (!apex_name.ok()) { + return apex_name.error(); + } + auto manifest_path = fmt::format("/apex/{}/apex_manifest.pb", *apex_name); + auto apex_manifest = ParseApexManifest(manifest_path); + if (!apex_manifest.ok()) { + return apex_manifest.error(); + } + return ApexInfo { + apex_manifest->name(), + apex_manifest->version(), + }; +} + +} // namespace widevine::apex \ No newline at end of file diff --git a/libwvdrmengine/apex/proto/widevine_apex_info.h b/libwvdrmengine/apex/proto/widevine_apex_info.h new file mode 100644 index 00000000..d4a34f46 --- /dev/null +++ b/libwvdrmengine/apex/proto/widevine_apex_info.h @@ -0,0 +1,34 @@ +/* + * Copyright 2023 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 + +#include + +#include + +namespace widevine::apex { + +struct ApexInfo { + std::string name; + int64_t version; +}; + +android::base::Result GetApexInfo(); + +} diff --git a/libwvdrmengine/src/service.cpp b/libwvdrmengine/src/service.cpp index d30ad182..b7a4a0b3 100644 --- a/libwvdrmengine/src/service.cpp +++ b/libwvdrmengine/src/service.cpp @@ -22,11 +22,19 @@ #include "WVCreatePluginFactories.h" #include "WVDrmFactory.h" +#include "widevine_apex_info.h" using ::wvdrm::hardware::drm::widevine::createDrmFactory; using ::wvdrm::hardware::drm::widevine::WVDrmFactory; int main(int /* argc */, char** /* argv */) { +#ifdef __ANDROID_APEX__ + { + auto info = widevine::apex::GetApexInfo(); + CHECK(info.ok()) << info.error(); + LOG(INFO) << "Starting from " << info->name << "(" << info->version << ")"; + } +#endif ABinderProcess_setThreadPoolMaxThreadCount(8); std::shared_ptr drmFactory = createDrmFactory();