1 /* 2 * Copyright (C) 2021 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.soundtrigger_middleware; 18 19 import android.annotation.NonNull; 20 import android.hardware.soundtrigger.V2_0.ISoundTriggerHw; 21 import android.os.HwBinder; 22 import android.os.RemoteException; 23 import android.os.ServiceManager; 24 import android.os.SystemProperties; 25 import android.util.Slog; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 30 /** 31 * This is the basic implementation of HalFactory, which uses either the default STHAL or a mock. 32 * 33 * The choice of which HAL to use is as follows: 34 * - Get the (int) value of "debug.soundtrigger_middleware.use_mock_hal" sysprop, if it doesn't 35 * exist, assume 0. 36 * - If the value is 0, use the default HAL on the device. Connect to the latest-version "default" 37 * instance declared in the device manifest (either AIDL or HIDL). 38 * - If the value is 2, connect to a "mock" instance of the latest v2.x (HIDL). 39 * - If the value is 3, connect to a "mock" instance of soundtrigger3 (AIDL). 40 * - Otherwise, throw. 41 */ 42 class DefaultHalFactory implements HalFactory { 43 private static final String TAG = "SoundTriggerMiddlewareDefaultHalFactory"; 44 45 private static final @NonNull ICaptureStateNotifier mCaptureStateNotifier = 46 new ExternalCaptureStateTracker(); 47 48 private static final int USE_DEFAULT_HAL = 0; 49 private static final int USE_MOCK_HAL_V2 = 2; 50 private static final int USE_MOCK_HAL_V3 = 3; 51 52 @Override create()53 public ISoundTriggerHal create() { 54 try { 55 int mockHal = SystemProperties.getInt("debug.soundtrigger_middleware.use_mock_hal", 56 USE_DEFAULT_HAL); 57 if (mockHal == USE_DEFAULT_HAL) { 58 // Use production HAL. 59 60 // Try soundtrigger3 (AIDL) first. 61 final String aidlServiceName = 62 android.hardware.soundtrigger3.ISoundTriggerHw.class.getCanonicalName() 63 + "/default"; 64 if (ServiceManager.isDeclared(aidlServiceName)) { 65 Slog.i(TAG, "Connecting to default soundtrigger3.ISoundTriggerHw"); 66 return new SoundTriggerHw3Compat(ServiceManager.waitForService(aidlServiceName), 67 () -> { 68 // This property needs to be defined in an init.rc script and 69 // trigger a HAL reboot. 70 SystemProperties.set("sys.audio.restart.hal", "1"); 71 }); 72 } 73 74 // Fallback to soundtrigger-V2.x (HIDL). 75 Slog.i(TAG, "Connecting to default soundtrigger-V2.x.ISoundTriggerHw"); 76 ISoundTriggerHw driver = ISoundTriggerHw.getService(true); 77 return SoundTriggerHw2Compat.create(driver, () -> { 78 // This property needs to be defined in an init.rc script and 79 // trigger a HAL reboot. 80 SystemProperties.set("sys.audio.restart.hal", "1"); 81 }, mCaptureStateNotifier); 82 } else if (mockHal == USE_MOCK_HAL_V2) { 83 // Use V2 mock. 84 Slog.i(TAG, "Connecting to mock soundtrigger-V2.x.ISoundTriggerHw"); 85 HwBinder.setTrebleTestingOverride(true); 86 try { 87 ISoundTriggerHw driver = ISoundTriggerHw.getService("mock", true); 88 return SoundTriggerHw2Compat.create(driver, () -> { 89 try { 90 driver.debug(null, new ArrayList<>(Arrays.asList("reboot"))); 91 } catch (Exception e) { 92 Slog.e(TAG, "Failed to reboot mock HAL", e); 93 } 94 }, mCaptureStateNotifier); 95 } finally { 96 HwBinder.setTrebleTestingOverride(false); 97 } 98 } else if (mockHal == USE_MOCK_HAL_V3) { 99 // Use V3 mock. 100 final String aidlServiceName = 101 android.hardware.soundtrigger3.ISoundTriggerHw.class.getCanonicalName() 102 + "/mock"; 103 Slog.i(TAG, "Connecting to mock soundtrigger3.ISoundTriggerHw"); 104 return new SoundTriggerHw3Compat(ServiceManager.waitForService(aidlServiceName), 105 () -> { 106 try { 107 ServiceManager.waitForService(aidlServiceName).shellCommand(null, 108 null, null, new String[]{"reboot"}, null, null); 109 } catch (Exception e) { 110 Slog.e(TAG, "Failed to reboot mock HAL", e); 111 } 112 }); 113 } else { 114 throw new RuntimeException("Unknown HAL mock version: " + mockHal); 115 } 116 } catch (RemoteException e) { 117 throw e.rethrowAsRuntimeException(); 118 } 119 } 120 } 121