diff --git a/services/core/Android.bp b/services/core/Android.bp index 2207821313760..821927d72428d 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -143,9 +143,10 @@ java_library_static { static_libs: [ "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.boot-V1.0-java", // HIDL + "android.hardware.boot-V1.1-java", // HIDL + "android.hardware.boot-V1.2-java", // HIDL + "android.hardware.boot-V1-java", // AIDL "android.hardware.broadcastradio-V2.0-java", "android.hardware.health-V1.0-java", // HIDL "android.hardware.health-V2.0-java", // HIDL diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index 13218731af705..9d5173a8da09e 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -36,7 +36,7 @@ import android.content.Context; import android.content.IntentSender; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.hardware.boot.V1_0.IBootControl; +import android.hardware.boot.IBootControl; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.Binder; @@ -48,6 +48,7 @@ import android.os.Process; import android.os.RecoverySystem; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.ServiceManager; import android.os.ShellCallback; import android.os.SystemProperties; import android.provider.DeviceConfig; @@ -66,6 +67,7 @@ import com.android.internal.widget.RebootEscrowListener; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ApexManager; +import com.android.server.recoverysystem.hal.BootControlHIDL; import libcore.io.IoUtils; @@ -155,18 +157,20 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo /** * The action to perform upon new resume on reboot prepare request for a given client. */ - @IntDef({ ROR_NEED_PREPARATION, + @IntDef({ROR_NEED_PREPARATION, ROR_SKIP_PREPARATION_AND_NOTIFY, - ROR_SKIP_PREPARATION_NOT_NOTIFY }) - private @interface ResumeOnRebootActionsOnRequest {} + ROR_SKIP_PREPARATION_NOT_NOTIFY}) + private @interface ResumeOnRebootActionsOnRequest { + } /** * The action to perform upon resume on reboot clear request for a given client. */ - @IntDef({ ROR_NOT_REQUESTED, + @IntDef({ROR_NOT_REQUESTED, ROR_REQUESTED_NEED_CLEAR, - ROR_REQUESTED_SKIP_CLEAR }) - private @interface ResumeOnRebootActionsOnClear {} + ROR_REQUESTED_SKIP_CLEAR}) + private @interface ResumeOnRebootActionsOnClear { + } /** * Fatal arm escrow errors from lock settings that means the RoR is in a bad state. So clients @@ -306,19 +310,26 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo * 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."); + public IBootControl getBootControl() throws RemoteException { + String serviceName = IBootControl.DESCRIPTOR + "/default"; + if (ServiceManager.isDeclared(serviceName)) { + Slog.i(TAG, + "AIDL version of BootControl HAL present, using instance " + serviceName); + return IBootControl.Stub.asInterface( + ServiceManager.waitForDeclaredService(serviceName)); } - android.hardware.boot.V1_2.IBootControl bootControlV12 = - android.hardware.boot.V1_2.IBootControl.castFrom(bootControlV10); - if (bootControlV12 == null) { + IBootControl bootcontrol = BootControlHIDL.getService(); + if (!BootControlHIDL.isServicePresent()) { + Slog.e(TAG, "Neither AIDL nor HIDL version of the BootControl HAL is present."); + return null; + } + + if (!BootControlHIDL.isV1_2ServicePresent()) { Slog.w(TAG, "Device doesn't implement boot control HAL V1_2."); return null; } - return bootControlV12; + return bootcontrol; } public void threadSleep(long millis) throws InterruptedException { @@ -526,7 +537,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY) != PackageManager.PERMISSION_GRANTED && mContext.checkCallingOrSelfPermission(android.Manifest.permission.REBOOT) - != PackageManager.PERMISSION_GRANTED) { + != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Caller must have " + android.Manifest.permission.RECOVERY + " or " + android.Manifest.permission.REBOOT + " for resume on reboot."); } @@ -738,7 +749,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo return true; } - android.hardware.boot.V1_2.IBootControl bootControl; + IBootControl bootControl; try { bootControl = mInjector.getBootControl(); } catch (RemoteException e) { @@ -972,8 +983,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo CompressedApexInfoList apexInfoList = getCompressedApexInfoList(packageFile); if (apexInfoList == null) { Log.i(TAG, "apex_info.pb not present in OTA package. " - + "Assuming device doesn't support compressed" - + "APEX, continueing without allocating space."); + + "Assuming device doesn't support compressed" + + "APEX, continueing without allocating space."); return true; } ApexManager apexManager = ApexManager.getInstance(); @@ -1160,6 +1171,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo /** * Reads the status from the uncrypt service which is usually represented as a percentage. + * * @return an integer representing the percentage completed * @throws IOException if there was an error reading the socket */ @@ -1169,6 +1181,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo /** * Sends a confirmation to the uncrypt service. + * * @throws IOException if there was an error writing to the socket */ public void sendAck() throws IOException { diff --git a/services/core/java/com/android/server/recoverysystem/hal/BootControlHIDL.java b/services/core/java/com/android/server/recoverysystem/hal/BootControlHIDL.java new file mode 100644 index 0000000000000..65325c297719a --- /dev/null +++ b/services/core/java/com/android/server/recoverysystem/hal/BootControlHIDL.java @@ -0,0 +1,178 @@ +/* + * 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 com.android.server.recoverysystem.hal; + +import android.hardware.boot.IBootControl; +import android.hardware.boot.V1_0.CommandResult; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; + +public class BootControlHIDL implements IBootControl { + private static final String TAG = "BootControlHIDL"; + + final android.hardware.boot.V1_0.IBootControl v1_hal; + final android.hardware.boot.V1_1.IBootControl v1_1_hal; + final android.hardware.boot.V1_2.IBootControl v1_2_hal; + + public static boolean isServicePresent() { + try { + android.hardware.boot.V1_0.IBootControl.getService(true); + } catch (RemoteException e) { + return false; + } + return true; + } + + public static boolean isV1_2ServicePresent() { + try { + android.hardware.boot.V1_2.IBootControl.getService(true); + } catch (RemoteException e) { + return false; + } + return true; + } + + public static BootControlHIDL getService() throws RemoteException { + android.hardware.boot.V1_0.IBootControl v1_hal = + android.hardware.boot.V1_0.IBootControl.getService(true); + android.hardware.boot.V1_1.IBootControl v1_1_hal = + android.hardware.boot.V1_1.IBootControl.castFrom(v1_hal); + android.hardware.boot.V1_2.IBootControl v1_2_hal = + android.hardware.boot.V1_2.IBootControl.castFrom(v1_hal); + return new BootControlHIDL(v1_hal, v1_1_hal, v1_2_hal); + } + + private BootControlHIDL(android.hardware.boot.V1_0.IBootControl v1_hal, + android.hardware.boot.V1_1.IBootControl v1_1_hal, + android.hardware.boot.V1_2.IBootControl v1_2_hal) throws RemoteException { + this.v1_hal = v1_hal; + this.v1_1_hal = v1_1_hal; + this.v1_2_hal = v1_2_hal; + if (v1_hal == null) { + throw new RemoteException("Failed to find V1.0 BootControl HIDL"); + } + if (v1_2_hal != null) { + Slog.i(TAG, "V1.2 version of BootControl HIDL HAL available, using V1.2"); + } else if (v1_1_hal != null) { + Slog.i(TAG, "V1.1 version of BootControl HIDL HAL available, using V1.1"); + } else { + Slog.i(TAG, "V1.0 version of BootControl HIDL HAL available, using V1.0"); + } + } + + @Override + public IBinder asBinder() { + return null; + } + + @Override + public int getActiveBootSlot() throws RemoteException { + if (v1_2_hal == null) { + throw new RemoteException("getActiveBootSlot() requires V1.2 BootControl HAL"); + } + return v1_2_hal.getActiveBootSlot(); + } + + @Override + public int getCurrentSlot() throws RemoteException { + return v1_hal.getCurrentSlot(); + } + + @Override + public int getNumberSlots() throws RemoteException { + return v1_hal.getNumberSlots(); + } + + @Override + public int getSnapshotMergeStatus() throws RemoteException { + if (v1_1_hal == null) { + throw new RemoteException("getSnapshotMergeStatus() requires V1.1 BootControl HAL"); + } + return v1_1_hal.getSnapshotMergeStatus(); + } + + @Override + public String getSuffix(int slot) throws RemoteException { + return v1_hal.getSuffix(slot); + } + + @Override + public boolean isSlotBootable(int slot) throws RemoteException { + int ret = v1_hal.isSlotBootable(slot); + if (ret == -1) { + throw new RemoteException( + "isSlotBootable() failed, Slot %d might be invalid.".formatted(slot)); + } + return ret != 0; + } + + @Override + public boolean isSlotMarkedSuccessful(int slot) throws RemoteException { + int ret = v1_hal.isSlotMarkedSuccessful(slot); + if (ret == -1) { + throw new RemoteException( + "isSlotMarkedSuccessful() failed, Slot %d might be invalid.".formatted(slot)); + } + return ret != 0; + } + + @Override + public void markBootSuccessful() throws RemoteException { + CommandResult res = v1_hal.markBootSuccessful(); + if (!res.success) { + throw new RemoteException("Error markBootSuccessful() " + res.errMsg); + } + } + + @Override + public void setActiveBootSlot(int slot) throws RemoteException { + CommandResult res = v1_hal.setActiveBootSlot(slot); + if (!res.success) { + throw new RemoteException("Error setActiveBootSlot(%d) %s".formatted(slot, res.errMsg)); + } + } + + @Override + public void setSlotAsUnbootable(int slot) throws RemoteException { + CommandResult res = v1_hal.setSlotAsUnbootable(slot); + if (!res.success) { + throw new RemoteException( + "Error setSlotAsUnbootable(%d) %s".formatted(slot, res.errMsg)); + } + } + + @Override + public void setSnapshotMergeStatus(int status) throws RemoteException { + if (v1_1_hal == null) { + throw new RemoteException("getSnapshotMergeStatus() requires V1.1 BootControl HAL"); + } + if (!v1_1_hal.setSnapshotMergeStatus(status)) { + throw new RemoteException("Error setSnapshotMergeStatus(%d)".formatted(status)); + } + } + + @Override + public int getInterfaceVersion() throws RemoteException { + return 1; + } + + @Override + public String getInterfaceHash() throws RemoteException { + return v1_hal.interfaceDescriptor(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java index 5234bb725a8f6..63d6768005127 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -46,7 +46,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.hardware.boot.IBootControl; import android.os.Handler; import android.os.IPowerManager; import android.os.IRecoverySystemProgressListener; diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java index 27e953f30fa05..f1cf48bc5f201 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java @@ -17,7 +17,7 @@ package com.android.server.recoverysystem; import android.content.Context; -import android.hardware.boot.V1_2.IBootControl; +import android.hardware.boot.IBootControl; import android.os.PowerManager; import com.android.internal.widget.LockSettingsInternal;