Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
capntrips committed Oct 16, 2023
0 parents commit 77dc265
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea/
CMakeLists.txt
cmake-build-debug/
39 changes: 39 additions & 0 deletions Android.bp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
cc_binary {
name: "oemlock",
srcs: ["oemlock.cpp"],
cflags: [
"-Wall",
"-Werror",
],
static_libs: [
"[email protected]",
"android.hardware.oemlock-V1-ndk",
"liboem_lock_client"
],
shared_libs: [
"libbinder_ndk",
"liblog",
"libbase",
"libcutils",
"libhidlbase",
"libutils",
],
}

cc_library {
name: "liboem_lock_client",
srcs: [
"OemLockClient.cpp"
],
export_include_dirs: ["include"],
export_shared_lib_headers: ["android.hardware.oemlock-V1-ndk"],
shared_libs: [
"android.hardware.oemlock-V1-ndk",
"[email protected]",
"libhidlbase",
"libbinder_ndk",
"libbase",
"libcutils",
"libutils",
],
}
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2023 capntrips

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
124 changes: 124 additions & 0 deletions OemLockClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include <OemLockClient.h>

#include <aidl/android/hardware/oemlock/IOemLock.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/hardware/oemlock/1.0/IOemLock.h>
#include "utils/StrongPointer.h"

using android::hardware::oemlock::V1_0::OemLockStatus;

namespace android::hal {
class OemLockClientAidl final : public OemLockClient {
using IOemLock = ::aidl::android::hardware::oemlock::IOemLock;

public:
OemLockClientAidl(std::shared_ptr<IOemLock> module) : module_(module) {}

OemLockVersion GetVersion() const override { return OemLockVersion::OEMLOCK_AIDL; }

~OemLockClientAidl() = default;
std::optional<bool> IsOemUnlockAllowedByCarrier() const {
bool ret = false;
const auto status = module_->isOemUnlockAllowedByCarrier(&ret);
if (!status.isOk()) {
LOG(ERROR) << __FUNCTION__ << "()"
<< " failed " << status.getDescription();
return {};
}
return ret;
}

std::optional<bool> IsOemUnlockAllowedByDevice() const {
bool ret = false;
const auto status = module_->isOemUnlockAllowedByDevice(&ret);
if (!status.isOk()) {
LOG(ERROR) << __FUNCTION__ << "()"
<< " failed " << status.getDescription();
return {};
}
return ret;
}

private:
const std::shared_ptr<IOemLock> module_;
};

using namespace android::hardware::oemlock;

class OemLockClientHIDL final : public OemLockClient {
public:
OemLockClientHIDL(android::sp<V1_0::IOemLock> module_v1)
: module_v1_(module_v1) {
CHECK(module_v1_ != nullptr);
}
OemLockVersion GetVersion() const override { return OemLockVersion::OEMLOCK_V1_0; }
std::optional<bool> IsOemUnlockAllowedByCarrier() const {
bool allowed;
OemLockStatus status;
const auto ret = module_v1_->isOemUnlockAllowedByCarrier([&](OemLockStatus s, bool a) {
status = s;
allowed = a;
});
if (!ret.isOk()) {
LOG(ERROR) << __FUNCTION__ << "()"
<< " failed " << ret.description();
return {};
}
if (status == V1_0::OemLockStatus::FAILED) {
return {};
}
return allowed;
}

std::optional<bool> IsOemUnlockAllowedByDevice() const {
bool allowed;
OemLockStatus status;
const auto ret = module_v1_->isOemUnlockAllowedByDevice([&](OemLockStatus s, bool a) {
status = s;
allowed = a;
});
if (!ret.isOk()) {
LOG(ERROR) << __FUNCTION__ << "()"
<< " failed " << ret.description();
return {};
}
if (status == V1_0::OemLockStatus::FAILED) {
return {};
}
return allowed;
}

private:
android::sp<V1_0::IOemLock> module_v1_;
};

std::unique_ptr<OemLockClient> OemLockClient::WaitForService() {
const auto instance_name =
std::string(::aidl::android::hardware::oemlock::IOemLock::descriptor) + "/default";

if (AServiceManager_isDeclared(instance_name.c_str())) {
auto module = ::aidl::android::hardware::oemlock::IOemLock::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
if (module == nullptr) {
LOG(ERROR) << "AIDL " << instance_name
<< " is declared but waitForService returned nullptr.";
return nullptr;
}
LOG(INFO) << "Using AIDL version of IOemLock";
return std::make_unique<OemLockClientAidl>(module);
}
LOG(INFO) << "AIDL IOemLock not available, falling back to HIDL.";

android::sp<V1_0::IOemLock> v1_0_module;
v1_0_module = V1_0::IOemLock::getService();
if (v1_0_module == nullptr) {
LOG(ERROR) << "Error getting oemlock v1.0 module.";
return nullptr;
}
LOG(INFO) << "Using HIDL version 1.0 of IOemLock";

return std::make_unique<OemLockClientHIDL>(v1_0_module);
}

} // namespace android::hal
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Oem Lock

Oem Lock is an Android command-line tool that checks whether OEM unlock is allowed by the carrier and device.

## Usage

```bash
oemlock hal-info
oemlock is-oem-unlock-allowed-by-carrier
oemlock is-oem-unlock-allowed-by-device
```
31 changes: 31 additions & 0 deletions include/OemLockClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef __OEMLOCK_OEMLOCKCLIENT_H_
#define __OEMLOCK_OEMLOCKCLIENT_H_

#include <aidl/android/hardware/oemlock/OemLockSecureStatus.h>

#include <stdint.h>

#include <memory>
#include <optional>

namespace android::hal {

enum class OemLockVersion { OEMLOCK_V1_0, OEMLOCK_AIDL };

class OemLockClient {
public:
using OemLockSecureStatus = aidl::android::hardware::oemlock::OemLockSecureStatus;
virtual ~OemLockClient() = default;
virtual OemLockVersion GetVersion() const = 0;
// Check if OEM unlock is allowed by the carrier. Return empty optional if the RPC call failed.
[[nodiscard]] virtual std::optional<bool> IsOemUnlockAllowedByCarrier() const = 0;

// Check if OEM unlock is allowed by the device. Return empty optional if the RPC call failed.
[[nodiscard]] virtual std::optional<bool> IsOemUnlockAllowedByDevice() const = 0;

[[nodiscard]] static std::unique_ptr<OemLockClient> WaitForService();
};

} // namespace android::hal

#endif //__OEMLOCK_OEMLOCKCLIENT_H_
89 changes: 89 additions & 0 deletions oemlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <optional>
#include <sstream>

#include <OemLockClient.h>
#include <android/hardware/oemlock/1.0/IOemLock.h>
#include <sysexits.h>

using android::sp;

using aidl::android::hardware::oemlock::OemLockSecureStatus;

using android::hal::OemLockClient;
using android::hal::OemLockVersion;

static void usage(FILE* where, int /* argc */, char* argv[]) {
fprintf(where,
"%s - command-line wrapper for the oemlock HAL.\n"
"\n"
"Usage:\n"
" %s COMMAND\n"
"\n"
"Commands:\n"
" hal-info - Show info about oemlock HAL used.\n"
" is-oem-unlock-allowed-by-carrier - Returns 0 only if OEM unlock is allowed by the carrier.\n"
" is-oem-unlock-allowed-by-device - Returns 0 only if OEM unlock ia allowed by the device.\n",
argv[0], argv[0]);
}

static int handle_return(const std::optional<bool>& ret, const char* errStr) {
if (!ret.has_value()) {
fprintf(stderr, errStr, "");
return EX_SOFTWARE;
}
if (ret.value()) {
printf("%d\n", ret.value());
return EX_OK;
}
printf("%d\n", ret.value());
return EX_SOFTWARE;
}

static constexpr auto ToString(OemLockVersion ver) {
switch (ver) {
case OemLockVersion::OEMLOCK_V1_0:
return "[email protected]::IOemLock";
case OemLockVersion::OEMLOCK_AIDL:
return "android.hardware.oemlock@aidl::IOemLock";
}
}

static int do_hal_info(const OemLockClient* module) {
fprintf(stdout, "HAL Version: %s\n", ToString(module->GetVersion()));
return EX_OK;
}

static int do_is_oem_unlock_allowed_by_carrier(OemLockClient* module) {
const auto ret = module->IsOemUnlockAllowedByCarrier();
return handle_return(ret, "Error calling isOemUnlockAllowedByCarrier()\n");
}

static int do_is_oem_unlock_allowed_by_device(OemLockClient* module) {
const auto ret = module->IsOemUnlockAllowedByDevice();
return handle_return(ret, "Error calling isOemUnlockAllowedByDevice()\n");
}

int main(int argc, char* argv[]) {
const auto client = android::hal::OemLockClient::WaitForService();
if (client == nullptr) {
fprintf(stderr, "Failed to get oemlock module.\n");
return EX_SOFTWARE;
}

if (argc < 2) {
usage(stderr, argc, argv);
return EX_USAGE;
}

if (strcmp(argv[1], "hal-info") == 0) {
return do_hal_info(client.get());
} else if (strcmp(argv[1], "is-oem-unlock-allowed-by-carrier") == 0) {
return do_is_oem_unlock_allowed_by_carrier(client.get());
} else if (strcmp(argv[1], "is-oem-unlock-allowed-by-device") == 0) {
return do_is_oem_unlock_allowed_by_device(client.get());
}

// Parameter not matched, print usage
usage(stderr, argc, argv);
return EX_USAGE;
}

0 comments on commit 77dc265

Please sign in to comment.