Skip to content
Snippets Groups Projects
Commit 097aabdb authored by Tianjie Xu's avatar Tianjie Xu Committed by Automerger Merge Worker
Browse files

Merge "Check slot in reboot function" am: 70127316 am: 4635bad1 am: 3720d381

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1504110

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I9f3568bf1c225ed9b9e498c0ea792804d8623f56
parents e8295597 3720d381
No related branches found
No related tags found
No related merge requests found
......@@ -120,6 +120,9 @@ java_library_static {
"time_zone_distro",
"time_zone_distro_installer",
"android.hardware.authsecret-V1.0-java",
"android.hardware.boot-V1.0-java",
"android.hardware.boot-V1.1-java",
"android.hardware.boot-V1.2-java",
"android.hardware.broadcastradio-V2.0-java",
"android.hardware.health-V1.0-java",
"android.hardware.health-V2.0-java",
......
......@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.hardware.boot.V1_0.IBootControl;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Binder;
......@@ -73,6 +74,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
@VisibleForTesting
static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
@VisibleForTesting
static final String AB_UPDATE = "ro.build.ab_update";
private static final Object sRequestLock = new Object();
......@@ -177,6 +180,25 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
return socket;
}
/**
* Throws remote exception if there's an error getting the boot control HAL.
* Returns null if the boot control HAL's version is older than V1_2.
*/
public android.hardware.boot.V1_2.IBootControl getBootControl() throws RemoteException {
IBootControl bootControlV10 = IBootControl.getService(true);
if (bootControlV10 == null) {
throw new RemoteException("Failed to get boot control HAL V1_0.");
}
android.hardware.boot.V1_2.IBootControl bootControlV12 =
android.hardware.boot.V1_2.IBootControl.castFrom(bootControlV10);
if (bootControlV12 == null) {
Slog.w(TAG, "Device doesn't implement boot control HAL V1_2.");
return null;
}
return bootControlV12;
}
public void threadSleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
......@@ -476,6 +498,56 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
return needClear ? ROR_REQUESTED_NEED_CLEAR : ROR_REQUESTED_SKIP_CLEAR;
}
private boolean isAbDevice() {
return "true".equalsIgnoreCase(mInjector.systemPropertiesGet(AB_UPDATE));
}
private boolean verifySlotForNextBoot(boolean slotSwitch) {
if (!isAbDevice()) {
Slog.w(TAG, "Device isn't a/b, skipping slot verification.");
return true;
}
android.hardware.boot.V1_2.IBootControl bootControl;
try {
bootControl = mInjector.getBootControl();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get the boot control HAL " + e);
return false;
}
// TODO(xunchang) enforce boot control V1_2 HAL on devices using multi client RoR
if (bootControl == null) {
Slog.w(TAG, "Cannot get the boot control HAL, skipping slot verification.");
return true;
}
int current_slot;
int next_active_slot;
try {
current_slot = bootControl.getCurrentSlot();
if (current_slot != 0 && current_slot != 1) {
throw new IllegalStateException("Current boot slot should be 0 or 1, got "
+ current_slot);
}
next_active_slot = bootControl.getActiveBootSlot();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to query the active slots", e);
return false;
}
int expected_active_slot = current_slot;
if (slotSwitch) {
expected_active_slot = current_slot == 0 ? 1 : 0;
}
if (next_active_slot != expected_active_slot) {
Slog.w(TAG, "The next active boot slot doesn't match the expected value, "
+ "expected " + expected_active_slot + ", got " + next_active_slot);
return false;
}
return true;
}
private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
if (packageName == null) {
Slog.w(TAG, "Missing packageName when rebooting with lskf.");
......@@ -485,7 +557,10 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
return false;
}
// TODO(xunchang) check the slot to boot into, and fail the reboot upon slot mismatch.
if (!verifySlotForNextBoot(slotSwitch)) {
return false;
}
// TODO(xunchang) write the vbmeta digest along with the escrowKey before reboot.
if (!mInjector.getLockSettingsService().armRebootEscrow()) {
Slog.w(TAG, "Failure to escrow key for reboot");
......
......@@ -76,7 +76,7 @@ public class RecoverySystemShellCommand extends ShellCommand {
private int rebootAndApply() throws RemoteException {
String packageName = getNextArgRequired();
String rebootReason = getNextArgRequired();
boolean success = mService.rebootWithLskf(packageName, rebootReason, true);
boolean success = mService.rebootWithLskf(packageName, rebootReason, false);
PrintWriter pw = getOutPrintWriter();
// Keep the old message for cts test.
pw.printf("%s Reboot and apply status: %s\n", packageName,
......
......@@ -35,6 +35,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.hardware.boot.V1_2.IBootControl;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.IRecoverySystemProgressListener;
......@@ -68,12 +69,13 @@ public class RecoverySystemServiceTest {
private IThermalService mIThermalService;
private FileWriter mUncryptUpdateFileWriter;
private LockSettingsInternal mLockSettingsInternal;
private IBootControl mIBootControl;
private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package";
private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package";
@Before
public void setup() {
public void setup() throws Exception {
mContext = mock(Context.class);
mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties();
mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class);
......@@ -88,8 +90,13 @@ public class RecoverySystemServiceTest {
PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager,
mIThermalService, new Handler(looper));
mIBootControl = mock(IBootControl.class);
when(mIBootControl.getCurrentSlot()).thenReturn(0);
when(mIBootControl.getActiveBootSlot()).thenReturn(1);
mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties,
powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal);
powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal,
mIBootControl);
}
@Test
......@@ -332,6 +339,15 @@ public class RecoverySystemServiceTest {
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
}
@Test
public void rebootWithLskf_slotMismatch_Failure() throws Exception {
assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
mRecoverySystemService.onPreparedForReboot(true);
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false),
is(false));
}
@Test
public void rebootWithLskf_withoutPrepare_Failure() throws Exception {
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
......
......@@ -17,6 +17,7 @@
package com.android.server.recoverysystem;
import android.content.Context;
import android.hardware.boot.V1_2.IBootControl;
import android.os.PowerManager;
import com.android.internal.widget.LockSettingsInternal;
......@@ -30,16 +31,19 @@ public class RecoverySystemServiceTestable extends RecoverySystemService {
private final FileWriter mUncryptPackageFileWriter;
private final UncryptSocket mUncryptSocket;
private final LockSettingsInternal mLockSettingsInternal;
private final IBootControl mIBootControl;
MockInjector(Context context, FakeSystemProperties systemProperties,
PowerManager powerManager, FileWriter uncryptPackageFileWriter,
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) {
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal,
IBootControl bootControl) {
super(context);
mSystemProperties = systemProperties;
mPowerManager = powerManager;
mUncryptPackageFileWriter = uncryptPackageFileWriter;
mUncryptSocket = uncryptSocket;
mLockSettingsInternal = lockSettingsInternal;
mIBootControl = bootControl;
}
@Override
......@@ -85,13 +89,19 @@ public class RecoverySystemServiceTestable extends RecoverySystemService {
public LockSettingsInternal getLockSettingsService() {
return mLockSettingsInternal;
}
@Override
public IBootControl getBootControl() {
return mIBootControl;
}
}
RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties,
PowerManager powerManager, FileWriter uncryptPackageFileWriter,
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) {
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal,
IBootControl bootControl) {
super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter,
uncryptSocket, lockSettingsInternal));
uncryptSocket, lockSettingsInternal, bootControl));
}
public static class FakeSystemProperties {
......@@ -102,6 +112,8 @@ public class RecoverySystemServiceTestable extends RecoverySystemService {
|| RecoverySystemService.INIT_SERVICE_SETUP_BCB.equals(key)
|| RecoverySystemService.INIT_SERVICE_CLEAR_BCB.equals(key)) {
return null;
} else if (RecoverySystemService.AB_UPDATE.equals(key)) {
return "true";
} else {
throw new IllegalArgumentException("unexpected test key: " + key);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment