1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.recoverysystem.hal; 18 19 import android.hardware.boot.IBootControl; 20 import android.hardware.boot.V1_0.CommandResult; 21 import android.os.IBinder; 22 import android.os.RemoteException; 23 import android.util.Slog; 24 25 import java.util.NoSuchElementException; 26 27 public class BootControlHIDL implements IBootControl { 28 private static final String TAG = "BootControlHIDL"; 29 30 final android.hardware.boot.V1_0.IBootControl v1_hal; 31 final android.hardware.boot.V1_1.IBootControl v1_1_hal; 32 final android.hardware.boot.V1_2.IBootControl v1_2_hal; 33 isServicePresent()34 public static boolean isServicePresent() { 35 try { 36 android.hardware.boot.V1_0.IBootControl.getService(true); 37 } catch (RemoteException | NoSuchElementException e) { 38 return false; 39 } 40 return true; 41 } 42 isV1_2ServicePresent()43 public static boolean isV1_2ServicePresent() { 44 try { 45 android.hardware.boot.V1_2.IBootControl.getService(true); 46 } catch (RemoteException | NoSuchElementException e) { 47 return false; 48 } 49 return true; 50 } 51 getService()52 public static BootControlHIDL getService() throws RemoteException { 53 android.hardware.boot.V1_0.IBootControl v1_hal = 54 android.hardware.boot.V1_0.IBootControl.getService(true); 55 android.hardware.boot.V1_1.IBootControl v1_1_hal = 56 android.hardware.boot.V1_1.IBootControl.castFrom(v1_hal); 57 android.hardware.boot.V1_2.IBootControl v1_2_hal = 58 android.hardware.boot.V1_2.IBootControl.castFrom(v1_hal); 59 return new BootControlHIDL(v1_hal, v1_1_hal, v1_2_hal); 60 } 61 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)62 private BootControlHIDL(android.hardware.boot.V1_0.IBootControl v1_hal, 63 android.hardware.boot.V1_1.IBootControl v1_1_hal, 64 android.hardware.boot.V1_2.IBootControl v1_2_hal) throws RemoteException { 65 this.v1_hal = v1_hal; 66 this.v1_1_hal = v1_1_hal; 67 this.v1_2_hal = v1_2_hal; 68 if (v1_hal == null) { 69 throw new RemoteException("Failed to find V1.0 BootControl HIDL"); 70 } 71 if (v1_2_hal != null) { 72 Slog.i(TAG, "V1.2 version of BootControl HIDL HAL available, using V1.2"); 73 } else if (v1_1_hal != null) { 74 Slog.i(TAG, "V1.1 version of BootControl HIDL HAL available, using V1.1"); 75 } else { 76 Slog.i(TAG, "V1.0 version of BootControl HIDL HAL available, using V1.0"); 77 } 78 } 79 80 @Override asBinder()81 public IBinder asBinder() { 82 return null; 83 } 84 85 @Override getActiveBootSlot()86 public int getActiveBootSlot() throws RemoteException { 87 if (v1_2_hal == null) { 88 throw new RemoteException("getActiveBootSlot() requires V1.2 BootControl HAL"); 89 } 90 return v1_2_hal.getActiveBootSlot(); 91 } 92 93 @Override getCurrentSlot()94 public int getCurrentSlot() throws RemoteException { 95 return v1_hal.getCurrentSlot(); 96 } 97 98 @Override getNumberSlots()99 public int getNumberSlots() throws RemoteException { 100 return v1_hal.getNumberSlots(); 101 } 102 103 @Override getSnapshotMergeStatus()104 public int getSnapshotMergeStatus() throws RemoteException { 105 if (v1_1_hal == null) { 106 throw new RemoteException("getSnapshotMergeStatus() requires V1.1 BootControl HAL"); 107 } 108 return v1_1_hal.getSnapshotMergeStatus(); 109 } 110 111 @Override getSuffix(int slot)112 public String getSuffix(int slot) throws RemoteException { 113 return v1_hal.getSuffix(slot); 114 } 115 116 @Override isSlotBootable(int slot)117 public boolean isSlotBootable(int slot) throws RemoteException { 118 int ret = v1_hal.isSlotBootable(slot); 119 if (ret == -1) { 120 throw new RemoteException( 121 "isSlotBootable() failed, Slot %d might be invalid.".formatted(slot)); 122 } 123 return ret != 0; 124 } 125 126 @Override isSlotMarkedSuccessful(int slot)127 public boolean isSlotMarkedSuccessful(int slot) throws RemoteException { 128 int ret = v1_hal.isSlotMarkedSuccessful(slot); 129 if (ret == -1) { 130 throw new RemoteException( 131 "isSlotMarkedSuccessful() failed, Slot %d might be invalid.".formatted(slot)); 132 } 133 return ret != 0; 134 } 135 136 @Override markBootSuccessful()137 public void markBootSuccessful() throws RemoteException { 138 CommandResult res = v1_hal.markBootSuccessful(); 139 if (!res.success) { 140 throw new RemoteException("Error markBootSuccessful() " + res.errMsg); 141 } 142 } 143 144 @Override setActiveBootSlot(int slot)145 public void setActiveBootSlot(int slot) throws RemoteException { 146 CommandResult res = v1_hal.setActiveBootSlot(slot); 147 if (!res.success) { 148 throw new RemoteException("Error setActiveBootSlot(%d) %s".formatted(slot, res.errMsg)); 149 } 150 } 151 152 @Override setSlotAsUnbootable(int slot)153 public void setSlotAsUnbootable(int slot) throws RemoteException { 154 CommandResult res = v1_hal.setSlotAsUnbootable(slot); 155 if (!res.success) { 156 throw new RemoteException( 157 "Error setSlotAsUnbootable(%d) %s".formatted(slot, res.errMsg)); 158 } 159 } 160 161 @Override setSnapshotMergeStatus(int status)162 public void setSnapshotMergeStatus(int status) throws RemoteException { 163 if (v1_1_hal == null) { 164 throw new RemoteException("getSnapshotMergeStatus() requires V1.1 BootControl HAL"); 165 } 166 if (!v1_1_hal.setSnapshotMergeStatus(status)) { 167 throw new RemoteException("Error setSnapshotMergeStatus(%d)".formatted(status)); 168 } 169 } 170 171 @Override getInterfaceVersion()172 public int getInterfaceVersion() throws RemoteException { 173 return 1; 174 } 175 176 @Override getInterfaceHash()177 public String getInterfaceHash() throws RemoteException { 178 return v1_hal.interfaceDescriptor(); 179 } 180 } 181