1 /* 2 * Copyright (C) 2022 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 package com.android.car.oem; 17 18 import static android.car.oem.OemCarAudioFocusResult.EMPTY_OEM_CAR_AUDIO_FOCUS_RESULTS; 19 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.car.builtin.util.Slogf; 23 import android.car.oem.IOemCarAudioFocusService; 24 import android.car.oem.OemCarAudioFocusEvaluationRequest; 25 import android.car.oem.OemCarAudioFocusResult; 26 import android.media.AudioFocusInfo; 27 import android.os.RemoteException; 28 import android.os.SystemClock; 29 import android.util.Log; 30 31 import com.android.car.CarLog; 32 import com.android.car.internal.util.IndentingPrintWriter; 33 import com.android.car.internal.util.LocalLog; 34 import com.android.internal.util.Preconditions; 35 36 import java.util.List; 37 import java.util.Optional; 38 39 /** 40 * Provides functionality of the OEM Audio Focus Service. 41 */ 42 public final class CarOemAudioFocusProxyService { 43 44 private static final String TAG = CarLog.tagFor(CarOemAudioFocusProxyService.class); 45 private static final int QUEUE_SIZE = 10; 46 47 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 48 private static final String CALLER_TAG = CarLog.tagFor(CarOemAudioFocusProxyService.class); 49 50 private final CarOemProxyServiceHelper mHelper; 51 private final IOemCarAudioFocusService mOemCarAudioFocusService; 52 @Nullable 53 private final LocalLog mLocalLog; // Is null if DBG is false. No logging will be produced. 54 55 CarOemAudioFocusProxyService(CarOemProxyServiceHelper helper, IOemCarAudioFocusService oemAudioFocusService)56 public CarOemAudioFocusProxyService(CarOemProxyServiceHelper helper, 57 IOemCarAudioFocusService oemAudioFocusService) { 58 mHelper = helper; 59 mOemCarAudioFocusService = oemAudioFocusService; 60 mLocalLog = DBG ? new LocalLog(QUEUE_SIZE) : null; 61 } 62 63 /** 64 * Updates audio focus changes. 65 */ notifyAudioFocusChange(List<AudioFocusInfo> currentFocusHolders, List<AudioFocusInfo> currentFocusLosers, int zoneId)66 public void notifyAudioFocusChange(List<AudioFocusInfo> currentFocusHolders, 67 List<AudioFocusInfo> currentFocusLosers, int zoneId) { 68 mHelper.doBinderOneWayCall(CALLER_TAG, () -> { 69 try { 70 mOemCarAudioFocusService 71 .notifyAudioFocusChange(currentFocusHolders, currentFocusLosers, zoneId); 72 } catch (RemoteException e) { 73 Slogf.e(TAG, e, 74 "audioFocusChanged call received RemoteException- currentFocusHolders:%s, " 75 + "currentFocusLosers:%s, ZoneId: %s, , calling to crash CarService", 76 currentFocusHolders, currentFocusLosers, zoneId); 77 } 78 }); 79 } 80 81 /** 82 * Requests to evaluate a new focus request 83 * @param request which includes the current audio focus info, current focus holders, 84 * and current focus losers. 85 * 86 * @return the focus evaluation results including any changes to the current focus stack. 87 */ 88 @NonNull evaluateAudioFocusRequest( @onNull OemCarAudioFocusEvaluationRequest request)89 public OemCarAudioFocusResult evaluateAudioFocusRequest( 90 @NonNull OemCarAudioFocusEvaluationRequest request) { 91 Preconditions.checkArgument(request != null, 92 "Audio focus evaluation request can not be null"); 93 94 long startTime = 0; 95 if (mLocalLog != null) { 96 startTime = SystemClock.uptimeMillis(); 97 } 98 99 Optional<OemCarAudioFocusResult> result = mHelper.doBinderCallWithTimeoutCrash(CALLER_TAG, 100 () -> { 101 try { 102 return mOemCarAudioFocusService.evaluateAudioFocusRequest(request); 103 } catch (RemoteException e) { 104 Slogf.e(TAG, e, 105 "evaluateAudioFocusRequest with request " + request); 106 } 107 return EMPTY_OEM_CAR_AUDIO_FOCUS_RESULTS; 108 }); 109 if (result.isEmpty()) { 110 return EMPTY_OEM_CAR_AUDIO_FOCUS_RESULTS; 111 } 112 113 OemCarAudioFocusResult focusResult = result.get(); 114 115 if (mLocalLog != null) { 116 mLocalLog.log(startTime + ", " + (SystemClock.uptimeMillis() - startTime)); 117 } 118 119 return focusResult; 120 } 121 dump(IndentingPrintWriter writer)122 public void dump(IndentingPrintWriter writer) { 123 if (mLocalLog == null) { 124 return; 125 } 126 writer.println("** Dump for CarOemAudioFocusProxyService **"); 127 mLocalLog.dump(writer); 128 // This print statement is used to indicate the end of a test. Do not change or remove 129 // this statement. 130 writer.println("Dump CarOemAudioFocusProxyService time log complete"); 131 } 132 } 133