标签:find require last dog iss hid osi include add
OEM锁可以禁止用户刷新bootloader或设备分区,运营商和设备本身都对是否允许OEM解锁有发言权,并且双方都必须同意允许这样做才能使解锁成为可能。
// 返回HAL的vendor特定标识符。
// 返回的名称不能由框架解释,而必须传递给vendor的代码,vendor的代码可以使用它来标识setOemUnlockAllowedByCarrier使用的安全协议。这使供应商无需维护设备到协议的映射即可识别协议。
// 返回值name表示实现的名字
1. getName()
// 更新运营商是否允许oem unlock
// 该实现可能需要供应商定义的签名来证明此请求的有效性,以增强其安全性。
// 参数allowed:flag的新值
// 参数signature:签名以证明此请求的有效性;如果不需要,则为空。
// 返回值status:如果成功更新了标志,则状态为OK;如果需要签名,但提供了错误的签名,则状态为INVALID_SIGNATURE;否则,如果更新失败,则状态为FAILED。
2. setOemUnlockAllowedByCarrier(bool allowed, vec<uint8_t> signature)
// 返回运营商是否已经允许oem unlock了
// 返回值status:如果flag被成功读取,则为OK
// 返回值allowed:flag现在的状态
3. isOemUnlockAllowedByCarrier()
// 更新设备是否允许oem unlock
// 参数allowed:flag的新值
// 返回值status:如果flag被成功更新,则为OK
frp设1,并算sha-256写进去就可以了
4. setOemUnlockAllowedByDevice(bool allowed)
// 返回设备是否已经允许oem unlock了
// 返回值status:如果flag被成功读取,则为OK
// 返回值allowed:flag现在的状态
读frp是否为1
5. isOemUnlockAllowedByDevice()
android/packages/apps/Settings/src/com/android/settings/development/OemUnlockPreferenceController.java
主要问题是开发者选项中,oemunlock选项为灰色
@Override
protected void onDeveloperOptionsSwitchEnabled() {
handleDeveloperOptionsToggled();
}
private void handleDeveloperOptionsToggled() {
// 打开开发者选项的时候,也会判断是否要设为灰色(已经unlock的就为灰色了),no_oem_unlock=true也为灰色
mPreference.setEnabled(enableOemUnlockPreference());
if (mPreference.isEnabled()) {
// Check restriction, disable mEnableOemUnlock and apply policy transparency.
mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
}
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
// oemunlock选项是否已经unlocked了。unlocked的话,这里返回true
mPreference.setChecked(isOemUnlockedAllowed());
updateOemUnlockSettingDescription();
// Showing mEnableOemUnlock preference as device has persistent data block.
mPreference.setDisabledByAdmin(null);
// oemunlock 选项是否要设为灰色(已经unlock的就为灰色了)
mPreference.setEnabled(enableOemUnlockPreference());
if (mPreference.isEnabled()) {
// Check restriction, disable mEnableOemUnlock and apply policy transparency.
mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
}
}
private boolean enableOemUnlockPreference() {
// 判断设备是否已经unlock了,已经unlock则直接返回true,所以已经unlock了的话,这个preference是灰色的
// 如果在overlay中配置了config_defaultFirstUserRestrictions的话,no_oem_unlock=true,对应
// 联网之后,no_oem_unlock就被设为false了,然后开发者选项中就不为灰色了
return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier();
}
boolean isBootloaderUnlocked() {
// 判断是否已经unlock了,判断ro.boot.flash.locked属性是否为0,为0则是unlock的,unlock则返回true;为1就是locked的(false)
return mOemLockManager.isDeviceOemUnlocked();
}
boolean isOemUnlockAllowedByUserAndCarrier() {
final UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
// 这里返回true
return mOemLockManager.isOemUnlockAllowedByCarrier()
// 这里一般是true的
&& !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET,
userHandle);
}
@VisibleForTesting
boolean isOemUnlockedAllowed() {
return mOemLockManager.isOemUnlockAllowed();
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isUnlocked = (Boolean) newValue;
if (isUnlocked) {
if (!showKeyguardConfirmation(mContext.getResources(),
REQUEST_CODE_ENABLE_OEM_UNLOCK)) {
// 弹出提示框,然后enable的话,就往frp分区写1
confirmEnableOemUnlock();
}
} else {
mOemLockManager.setOemUnlockAllowedByUser(false);
OemLockInfoDialog.show(mFragment);
}
return true;
}
@VisibleForTesting
void confirmEnableOemUnlock() {
EnableOemUnlockSettingWarningDialog.show(mFragment);
}
@Override
public void onClick(DialogInterface dialog, int which) {
final OemUnlockDialogHost host = (OemUnlockDialogHost) getTargetFragment();
if (host == null) {
return;
}
if (which == DialogInterface.BUTTON_POSITIVE) {
host.onOemUnlockDialogConfirmed();
} else {
host.onOemUnlockDialogDismissed();
}
}
@Override
public void onOemUnlockDialogConfirmed() {
final OemUnlockPreferenceController controller = getDevelopmentOptionsController(
OemUnlockPreferenceController.class);
controller.onOemUnlockConfirmed();
}
public void onOemUnlockConfirmed() {
// oemlock hal写1
// frp分区写1。两步都会去做
mOemLockManager.setOemUnlockAllowedByUser(true);
}
frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
try {
.....
SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
....
}
}
// 类被加载了不一定就会执行静态代码块,只有一个类被主动使用的时候,静态代码才会被执行!类被调用了,才会调用static代码块
static {
registerService(Context.OEM_LOCK_SERVICE, OemLockManager.class,
new StaticServiceFetcher<OemLockManager>() {
@Override
public OemLockManager createService() throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.OEM_LOCK_SERVICE);
IOemLockService oemLockService = IOemLockService.Stub.asInterface(b);
if (oemLockService != null) {
return new OemLockManager(oemLockService);
} else {
// not supported
return null;
}
}});
}
OemLockManager的函数调用都是调用OemLockService里面去的,oemlockmanager只是个接口
public boolean isDeviceOemUnlocked() {
try {
return mService.isDeviceOemUnlocked();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/frameworks/base/services/core/java/com/android/server/oemlock/OemLockService.java
@Override
public boolean isDeviceOemUnlocked() {
enforceOemUnlockReadPermission();
String locked = SystemProperties.get(FLASH_LOCK_PROP);
switch (locked) {
// 这个是0,返回的是true
case FLASH_LOCK_UNLOCKED:
return true;
default:
return false;
}
}
private static OemLock getOemLock(Context context) {
final IOemLock oemLockHal = VendorLock.getOemLockHalService();
// 是否使用oemlock hal;如果使用了oemlock hal,则使用oemlock hal
if (oemLockHal != null) {
Slog.i(TAG, "Using vendor lock via the HAL");
return new VendorLock(context, oemLockHal);
} else {
Slog.i(TAG, "Using persistent data block based lock");
//否则的话,就使用PersistentDataBlockLock
return new PersistentDataBlockLock(context);
}
}
public OemLockService(Context context) {
this(context, getOemLock(context));
}
OemLockService(Context context, OemLock oemLock) {
super(context);
mContext = context;
mOemLock = oemLock;
LocalServices.getService(UserManagerInternal.class)
.addUserRestrictionsListener(mUserRestrictionsListener);
}
@Override
public boolean isOemUnlockAllowedByCarrier() {
enforceManageCarrierOemUnlockPermission();
final long token = Binder.clearCallingIdentity();
try {
return mOemLock.isOemUnlockAllowedByCarrier();
} finally {
Binder.restoreCallingIdentity(token);
}
}
/** Currently MasterClearConfirm will call isOemUnlockAllowed()
* to sync PersistentDataBlockOemUnlockAllowedBit which
* is needed before factory reset
* TODO: Figure out better place to run sync e.g. adding new API
*/
@Override
public boolean isOemUnlockAllowed() {
enforceOemUnlockReadPermission();
final long token = Binder.clearCallingIdentity();
try {
// no_oem_unlock=false;所以isOemUnlockAllowedByCarrier为true
boolean allowed = mOemLock.isOemUnlockAllowedByCarrier()
// 所以主要看isOemUnlockAllowedByDevice:读/dev/block/by-name/frp分区的最后一位,看是否为1,为1则返回true
&& mOemLock.isOemUnlockAllowedByDevice();
// 往frp分区最后一位写allowed
setPersistentDataBlockOemUnlockAllowedBit(allowed);
return allowed;
} finally {
Binder.restoreCallingIdentity(token);
}
}
// The user has the final say so if they allow unlock, then the device allows the bootloader
// to OEM unlock it.
@Override
public void setOemUnlockAllowedByUser(boolean allowedByUser) {
if (ActivityManager.isUserAMonkey()) {
// Prevent a monkey from changing this
return;
}
enforceManageUserOemUnlockPermission();
enforceUserIsAdmin();
final long token = Binder.clearCallingIdentity();
try {
if (!isOemUnlockAllowedByAdmin()) {
throw new SecurityException("Admin does not allow OEM unlock");
}
if (!mOemLock.isOemUnlockAllowedByCarrier()) {
throw new SecurityException("Carrier does not allow OEM unlock");
}
// 如果用的是persistentdata的话,下面两个函数都是一样的功能,都是往frp分区写1
mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
// 往frp分区写1
setPersistentDataBlockOemUnlockAllowedBit(allowedByUser);
} finally {
Binder.restoreCallingIdentity(token);
}
}
framework/base/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
@Override
// no_oem_unlock=true则返回false;no_oem_unlock=false则返回true
boolean isOemUnlockAllowedByCarrier() {
return !UserManager.get(mContext)
.hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, UserHandle.SYSTEM);
}
@Override
boolean isOemUnlockAllowedByDevice() {
final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
if (pdbm == null) {
Slog.w(TAG, "PersistentDataBlock is not supported on this device");
return false;
}
return pdbm.getOemUnlockEnabled();
}
@Override
void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
// The method name is misleading as it really just means whether or not the device can be
// unlocked but doesn‘t actually do any unlocking.
final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
if (pdbm == null) {
Slog.w(TAG, "PersistentDataBlock is not supported on this device");
return;
}
pdbm.setOemUnlockEnabled(allowedByDevice);
}
android/frameworks/base/core/java/android/os/UserManager.java
@UnsupportedAppUsage
public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey,
UserHandle userHandle) {
return hasUserRestrictionForUser(restrictionKey, userHandle);
}
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
public boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
@NonNull UserHandle userHandle) {
try {
return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java
/** @return a specific user restriction that‘s in effect currently. */
@Override
public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) {
checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "hasUserRestriction");
return mLocalService.hasUserRestriction(restrictionKey, userId);
}
@Override
public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) {
// 检查是否有这个restrictionKey,里面有一个USER_RESTRICTIONS集合,包含所有的restrictionKey
// 经查看,是有DISALLOW_OEM_UNLOCK这个key的
if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
return false;
}
Bundle restrictions = getEffectiveUserRestrictions(userId);
// 获取key的值
return restrictions != null && restrictions.getBoolean(restrictionKey);
}
调用栈:
UserManagerService: writeUserLP com.android.server.pm.UserManagerService$UserData@d9662bc called at
UserManagerService: com.android.server.pm.UserManagerService.writeUserLP:2823
UserManagerService: com.android.server.pm.UserManagerService.fallbackToSingleUserLP:2791
UserManagerService: com.android.server.pm.UserManagerService.readUserListLP:2496
UserManagerService: com.android.server.pm.UserManagerService.<init>:624
UserManagerService: com.android.server.pm.UserManagerService.<init>:602
UserManagerService: com.android.server.pm.PackageManagerService.lambda$main$2:2595
UserManagerService: com.android.server.pm.-$$Lambda$PackageManagerService$xKD6SB7pISjc29qfmXIq5O_3OJw.produce:12
UserManagerService: com.android.server.pm.PackageManagerService$Injector$Singleton.get:910
UserManagerService: com.android.server.pm.PackageManagerService$Injector.getUserManagerService:1004
UserManagerService: com.android.server.pm.PackageManagerService.<init>:2871
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
| UserInfo.FLAG_PRIMARY;
// Create the system user
String systemUserType = UserManager.isHeadlessSystemUserMode() ?
UserManager.USER_TYPE_SYSTEM_HEADLESS : UserManager.USER_TYPE_FULL_SYSTEM;
flags |= mUserTypes.get(systemUserType).getDefaultUserInfoFlags();
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags, systemUserType);
UserData userData = putUserInfo(system);
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
mUserTypeVersion = UserTypeFactory.getUserTypeVersion();
Bundle restrictions = new Bundle();
try {
// 在这里会解析config_defaultFirstUserRestrictions配置
final String[] defaultFirstUserRestrictions = mContext.getResources().getStringArray(
com.android.internal.R.array.config_defaultFirstUserRestrictions);
for (String userRestriction : defaultFirstUserRestrictions) {
if (UserRestrictionsUtils.isValidRestriction(userRestriction)) {
// 然后给他写上true,所以no_oem_unlock=true
restrictions.putBoolean(userRestriction, true);
}
}
} catch (Resources.NotFoundException e) {
Slog.e(LOG_TAG, "Couldn‘t find resource: config_defaultFirstUserRestrictions", e);
}
if (!restrictions.isEmpty()) {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.updateRestrictions(UserHandle.USER_SYSTEM,
restrictions);
}
}
updateUserIds();
initDefaultGuestRestrictions();
// 然后这里写到了/data/system/users/0.xml文件
writeUserLP(userData);
writeUserListLP();
}
<?xml version=‘1.0‘ encoding=‘utf-8‘ standalone=‘yes‘ ?>
<user id="0" serialNumber="0" flags="3091" type="android.os.usertype.full.SYSTEM" created="0" lastLoggedIn="1620875315872" lastLoggedInFingerprint="Allwinner/ceres_b4/ceres-b4:11/RP1A.201005.006/eng.xx.20210512.114843:userdebug/test-keys" profileBadge="0">
<restrictions no_oem_unlock="true" />
<device_policy_local_restrictions />
</user>
调用栈:
UserManagerService: scheduleWriteUser called at
UserManagerService: com.android.server.pm.UserManagerService.scheduleWriteUser:2801
UserManagerService: com.android.server.pm.UserManagerService.updateUserRestrictionsInternalLR:2104
UserManagerService: com.android.server.pm.UserManagerService.setUserRestriction:2076
UserManagerService: android.os.IUserManager$Stub.onTransact:1165
UserManagerService: android.os.Binder.execTransactInternal:1154
UserManagerService: android.os.Binder.execTransact:1123
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: Applying user restrictions: userId=0 new=Bundle[{no_oem_unlock=false}] prev=Bundle[{no_oem_unlock=true}] called at
UserManagerService: com.android.server.pm.UserManagerService.updateUserRestrictionsInternalLR:2114
UserManagerService: com.android.server.pm.UserManagerService.setUserRestriction:2076
UserManagerService: android.os.IUserManager$Stub.onTransact:1165
UserManagerService: android.os.Binder.execTransactInternal:1154
UserManagerService: android.os.Binder.execTransact:1123
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: <bottom of call stack>
UserManagerService: writeUserLP com.android.server.pm.UserManagerService$UserData@d9662bc called at
UserManagerService: com.android.server.pm.UserManagerService.writeUserLP:2823
UserManagerService: com.android.server.pm.UserManagerService.access$1500:155
UserManagerService: com.android.server.pm.UserManagerService$MainHandler.handleMessage:4843
UserManagerService: android.os.Handler.dispatchMessage:106
UserManagerService: android.os.Looper.loop:223
UserManagerService: com.android.server.SystemServer.run:644
UserManagerService: com.android.server.SystemServer.main:419
UserManagerService: java.lang.reflect.Method.invoke:-2
UserManagerService: com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run:592
UserManagerService: com.android.internal.os.ZygoteInit.main:1062
大概的流程就是:
联网 -> GMS Core app调用setUserRestriction接口,设置no_oem_unlock=false -> updateUserRestrictionsInternalLR -> scheduleWriteUser -> writeUserLP:写到/data/system/users/0.xml文件
frameworks/base/services/core/java/com/android/server/PersistentDataBlockService.java
@Override
public boolean getOemUnlockEnabled() {
enforceOemUnlockReadPermission();
return doGetOemUnlockEnabled();
}
private boolean doGetOemUnlockEnabled() {
DataInputStream inputStream;
try {
// 读"ro.frp.pst"属性:/dev/block/by-name/frp
inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
} catch (FileNotFoundException e) {
Slog.e(TAG, "partition not available");
return false;
}
try {
synchronized (mLock) {
// 读/dev/block/by-name/frp分区的最后一位,看是否为1,为1则返回true
inputStream.skip(getBlockDeviceSize() - 1);
return inputStream.readByte() != 0;
}
} catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e);
return false;
} finally {
IoUtils.closeQuietly(inputStream);
}
}
@Override
public void setOemUnlockEnabled(boolean enabled) throws SecurityException {
// do not allow monkey to flip the flag
if (ActivityManager.isUserAMonkey()) {
return;
}
enforceOemUnlockWritePermission();
enforceIsAdmin();
if (enabled) {
// Do not allow oem unlock to be enabled if it‘s disallowed by a user restriction.
enforceUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
enforceUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
}
synchronized (mLock) {
// 往frp写1
doSetOemUnlockEnabledLocked(enabled);
// 计算digest值
computeAndWriteDigestLocked();
}
}
* The persistent data block is currently laid out as follows:
* | ---------BEGINNING OF PARTITION-------------|
* | Partition digest (32 bytes) |
* | --------------------------------------------|
* | PARTITION_TYPE_MARKER (4 bytes) |
* | --------------------------------------------|
* | FRP data block length (4 bytes) |
* | --------------------------------------------|
* | FRP data (variable length) |
* | --------------------------------------------|
* | ... |
* | --------------------------------------------|
* | Test mode data block (10000 bytes) |
* | --------------------------------------------|
* | | Test mode data length (4 bytes) |
* | --------------------------------------------|
* | | Test mode data (variable length) |
* | | ... |
* | --------------------------------------------|
* | FRP credential handle block (1000 bytes) |
* | --------------------------------------------|
* | | FRP credential handle length (4 bytes)|
* | --------------------------------------------|
* | | FRP credential handle (variable len) |
* | | ... |
* | --------------------------------------------|
* | OEM Unlock bit (1 byte) |
* | ---------END OF PARTITION-------------------|
// 最后一位就是oem unlock bit
private void doSetOemUnlockEnabledLocked(boolean enabled) {
FileOutputStream outputStream;
try {
outputStream = getBlockOutputStream();
} catch (IOException e) {
Slog.e(TAG, "partition not available", e);
return;
}
try {
FileChannel channel = outputStream.getChannel();
channel.position(getBlockDeviceSize() - 1);
ByteBuffer data = ByteBuffer.allocate(1);
// 这里判断是否为1
data.put(enabled ? (byte) 1 : (byte) 0);
data.flip();
// 往frp分区写
channel.write(data);
outputStream.flush();
} catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e);
return;
} finally {
SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
IoUtils.closeQuietly(outputStream);
}
}
private boolean computeAndWriteDigestLocked() {
byte[] digest = computeDigestLocked(null);
if (digest != null) {
DataOutputStream outputStream;
try {
outputStream = new DataOutputStream(getBlockOutputStream());
} catch (IOException e) {
Slog.e(TAG, "partition not available?", e);
return false;
}
try {
// 写digest
outputStream.write(digest, 0, DIGEST_SIZE_BYTES);
outputStream.flush();
} catch (IOException e) {
Slog.e(TAG, "failed to write block checksum", e);
return false;
} finally {
IoUtils.closeQuietly(outputStream);
}
return true;
} else {
return false;
}
}
// 计算digest
private byte[] computeDigestLocked(byte[] storedDigest) {
DataInputStream inputStream;
try {
inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
} catch (FileNotFoundException e) {
Slog.e(TAG, "partition not available?", e);
return null;
}
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// won‘t ever happen -- every implementation is required to support SHA-256
Slog.e(TAG, "SHA-256 not supported?", e);
IoUtils.closeQuietly(inputStream);
return null;
}
try {
if (storedDigest != null && storedDigest.length == DIGEST_SIZE_BYTES) {
inputStream.read(storedDigest);
} else {
inputStream.skipBytes(DIGEST_SIZE_BYTES);
}
int read;
byte[] data = new byte[1024];
md.update(data, 0, DIGEST_SIZE_BYTES); // include 0 checksum in digest
while ((read = inputStream.read(data)) != -1) {
md.update(data, 0, read);
}
} catch (IOException e) {
Slog.e(TAG, "failed to read partition", e);
return null;
} finally {
IoUtils.closeQuietly(inputStream);
}
return md.digest();
}
实现的版本也是往frp写1
#include <openssl/sha.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include "OemLockHidl.h"
namespace android {
namespace hardware {
namespace oemlock {
namespace V1_0 {
namespace implementation {
using ::android::base::ParseInt;
using ::android::base::ReadFileToString;
using ::android::base::ReadFullyAtOffset;
using ::android::base::Split;
using ::android::base::StringPrintf;
using ::android::base::unique_fd;
const std::string FRP_DEV_PATH = "/dev/block/by-name/frp";
#define DIGEST_SIZE_BYTES 32
static int64_t get_file_size(int fd) {
struct stat buf;
int ret = fstat(fd, &buf);
if (ret) return 0;
int64_t computed_size = 0;
if (S_ISREG(buf.st_mode)) {
computed_size = buf.st_size;
} else if (S_ISBLK(buf.st_mode)) {
uint64_t block_device_size = 0;
ret = ioctl(fd, BLKGETSIZE64, &block_device_size);
if (ret) return 0;
computed_size = block_device_size;
}
LOG(INFO) << "oemlock_impl get file size " << computed_size;
return computed_size;
}
Return<void> OemLockHidl::getName(getName_cb _hidl_cb)
{
OemLockStatus status = OemLockStatus::OK;
hidl_string name = "oemlock";
_hidl_cb(status, name);
return Void();
}
Return<OemLockSecureStatus> OemLockHidl::setOemUnlockAllowedByCarrier(bool allowed, const hidl_vec<uint8_t>& signature)
{
(void)allowed;
(void)signature;
OemLockSecureStatus status = OemLockSecureStatus::OK;
return status;
}
Return<void> OemLockHidl::isOemUnlockAllowedByCarrier(isOemUnlockAllowedByCarrier_cb _hidl_cb)
{
bool allowed = true;
OemLockStatus status = OemLockStatus::OK;
_hidl_cb(status, allowed);
return Void();
}
OemLockHidl::OemLockHidl() {}
} // namespace implementation
} // namespace V1_0
} // namespace oemlock
} // namespace hardware
} // namespace androi
Return<OemLockStatus> OemLockHidl::setOemUnlockAllowedByDevice(bool allowed)
{
OemLockStatus status = OemLockStatus::OK;
if (set_oemunlock_allowed_by_device_impl(allowed) < 0) {
LOG(ERROR) << "oemlock setOemUnlockAllowedByDevice fail";
status = OemLockStatus::FAILED;
}
return status;
}
int do_set_oemunlock_allowed_by_device(bool in_allowed)
{
unique_fd fd(TEMP_FAILURE_RETRY(open(FRP_DEV_PATH.c_str(), O_WRONLY | O_CLOEXEC | O_BINARY)));
if (fd < 0) {
LOG(ERROR) << "oemlock do_set_oemunlock_allowed_by_device open file fail";
return -1;
}
int64_t offset = get_file_size(fd) - 1;
if (offset < 0) {
LOG(ERROR) << "oemlock do_set_oemunlock_allowed_by_device get_file_size fail";
return -1;
}
LOG(INFO) << "oemlock_impl write oem unlock flag offset " << offset;
uint8_t flag = in_allowed ? (uint8_t) 1 : (uint8_t) 0;
LOG(INFO) << "oemlock_impl write oem unlock flag is " << flag;
if (lseek(fd, offset, SEEK_SET) < 0) {
LOG(ERROR) << "oemlock do_set_oemunlock_allowed_by_device lseek fail";
return -1;
}
if (write(fd, &flag, 1) < 0) {
LOG(ERROR) << "oemlock do_set_oemunlock_allowed_by_device write fail";
return -1;
}
return 0;
}
int compute_and_write_digest()
{
unique_fd fd(TEMP_FAILURE_RETRY(open(FRP_DEV_PATH.c_str(), O_RDWR | O_CLOEXEC | O_BINARY)));
if (fd < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest open file fail";
return -1;
}
int64_t data_size = get_file_size(fd) - DIGEST_SIZE_BYTES;
if (data_size < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest get_file_size fail";
return -1;
}
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(data_size);
std::unique_ptr<uint8_t[]> digest = std::make_unique<uint8_t[]>(DIGEST_SIZE_BYTES);
if (ReadFullyAtOffset(fd, data.get(), data_size, DIGEST_SIZE_BYTES) < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest ReadFullyAtOffset fail";
return -1;
}
SHA256_CTX sha256_ctx;
SHA256_Init(&sha256_ctx);
SHA256_Update(&sha256_ctx, data.get(), data_size);
SHA256_Final(digest.get(), &sha256_ctx);
if (lseek(fd, 0, SEEK_SET) < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest lseek fail";
return -1;
}
if (write(fd, digest.get(), DIGEST_SIZE_BYTES) < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest write fail";
return -1;
}
return 0;
}
int set_oemunlock_allowed_by_device_impl(bool in_allowed)
{
if (do_set_oemunlock_allowed_by_device(in_allowed) < 0) {
LOG(ERROR) << "oemlock do_set_oemunlock_allowed_by_device fail";
return -1;
}
if (compute_and_write_digest() < 0) {
LOG(ERROR) << "oemlock compute_and_write_digest fail";
return -1;
}
return 0;
}
int is_oemunlock_allowed_by_device_impl(bool *allowed) {
unique_fd fd(TEMP_FAILURE_RETRY(open(FRP_DEV_PATH.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY)));
if (fd < 0) {
LOG(ERROR) << "oemlock is_oemunlock_allowed_by_device_impl open file fail";
return -1;
}
int64_t offset = get_file_size(fd) - 1;
if (offset < 0) {
LOG(ERROR) << "oemlock is_oemunlock_allowed_by_device_impl get_file_size fail";
return -1;
}
LOG(INFO) << "oemlock_impl read oem unlock flag offset " << offset;
int flag;
if (ReadFullyAtOffset(fd, &flag, 1, offset) < 0) {
LOG(ERROR) << "oemlock is_oemunlock_allowed_by_device_impl ReadFullyAtOffset fail";
return -1;
}
LOG(INFO) << "oemlock_impl read oem unlock flag is " << flag;
*allowed = (flag == 1) ? true : false;
return 0;
}
Return<void> OemLockHidl::isOemUnlockAllowedByDevice(isOemUnlockAllowedByDevice_cb _hidl_cb)
{
OemLockStatus status = OemLockStatus::OK;
bool allowed = false;
if (is_oemunlock_allowed_by_device_impl(&allowed) < 0) {
LOG(ERROR) << "oemlock isOemUnlockAllowedByDevice fail";
status = OemLockStatus::FAILED;
}
_hidl_cb(status, allowed);
return Void();
}
由于GMS要求,要把config_defaultFirstUserRestrictions配置为no_oem_unlock,所以开发者选项为灰色
由于oemlock hal不能写frp分区(selinux neverallow规则),所以没办法实现oemlock hal写frp分区
所以暂时去掉config_defaultFirstUserRestrictions配置,让机器不用联网,就可以在开发者选项中打开oemlock选项
diff --git a/common/overlay/overlay/frameworks/base/core/res/res/values/config.xml b/common/overlay/overlay/frameworks/base/core/res/res/values/config.xml
old mode 100644
new mode 100755
index 61ca324..be9a5b0
--- a/common/overlay/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/common/overlay/overlay/frameworks/base/core/res/res/values/config.xml
@@ -718,4 +718,11 @@
</array>
<bool name="config_shutdownForceScreenOff">true</bool>
+
+ <!-- Package name for the device provisioning package. -->
+ <string name="config_deviceProvisioningPackage">com.google.android.apps.work.oobconfig</string>
+
+ <string-array translatable="false" name="config_defaultFirstUserRestrictions">
+ <item>"no_oem_unlock"</item>
+ </string-array>
</resources>
1. android去除安全模式
https://blog.csdn.net/qq_28534581/article/details/84885773
2. Android Verified Boot浅知分享
https://www.jianshu.com/p/d354280f1f27
标签:find require last dog iss hid osi include add
原文地址:https://www.cnblogs.com/pyjetson/p/14769333.html