/* * Copyright (C) 2018 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 android.hardware.hdmi; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; /** * HdmiAudioSystemClient represents HDMI-CEC logical device of type Audio System in the Android * system which acts as an audio system device such as sound bar. * *
HdmiAudioSystemClient provides methods that control, get information from TV/Display device * connected through HDMI bus. * * @hide */ public final class HdmiAudioSystemClient extends HdmiClient { private static final String TAG = "HdmiAudioSystemClient"; private static final int REPORT_AUDIO_STATUS_INTERVAL_MS = 500; private final Handler mHandler; private boolean mCanSendAudioStatus = true; private boolean mPendingReportAudioStatus; private int mLastVolume; private int mLastMaxVolume; private boolean mLastIsMute; @VisibleForTesting(visibility = Visibility.PACKAGE) public HdmiAudioSystemClient(IHdmiControlService service) { this(service, null); } @VisibleForTesting(visibility = Visibility.PACKAGE) public HdmiAudioSystemClient(IHdmiControlService service, @Nullable Handler handler) { super(service); mHandler = handler == null ? new Handler(Looper.getMainLooper()) : handler; } /** * Callback interface used to get the set System Audio Mode result. * * @hide */ public interface SetSystemAudioModeCallback { /** * Called when the input was changed. * * @param result the result of the set System Audio Mode */ void onComplete(int result); } /** @hide */ @Override public int getDeviceType() { return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM; } /** * Sends a Report Audio Status HDMI CEC command to TV devices when necessary. * * According to HDMI CEC specification, an audio system can report its audio status when System * Audio Mode is on, so that the TV can display the audio status of external amplifier. * * @hide */ public void sendReportAudioStatusCecCommand(boolean isMuteAdjust, int volume, int maxVolume, boolean isMute) { if (isMuteAdjust) { // always report audio status when it's muted/unmuted try { mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute); } catch (RemoteException e) { // do nothing. Reporting audio status is optional. } return; } mLastVolume = volume; mLastMaxVolume = maxVolume; mLastIsMute = isMute; if (mCanSendAudioStatus) { try { mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute); mCanSendAudioStatus = false; mHandler.postDelayed(new Runnable() { @Override public void run() { if (mPendingReportAudioStatus) { // report audio status if there is any pending message try { mService.reportAudioStatus(getDeviceType(), mLastVolume, mLastMaxVolume, mLastIsMute); mHandler.postDelayed(this, REPORT_AUDIO_STATUS_INTERVAL_MS); } catch (RemoteException e) { mCanSendAudioStatus = true; } finally { mPendingReportAudioStatus = false; } } else { mCanSendAudioStatus = true; } } }, REPORT_AUDIO_STATUS_INTERVAL_MS); } catch (RemoteException e) { // do nothing. Reporting audio status is optional. } } else { // if audio status cannot be sent, send it latter mPendingReportAudioStatus = true; } } /** * Set System Audio Mode on/off with audio system device. * * @param state true to set System Audio Mode on. False to set off. * @param callback callback offer the setting result. * * @hide */ public void setSystemAudioMode(boolean state, @NonNull SetSystemAudioModeCallback callback) { // TODO(b/217509829): implement this when needed. } /** * When device is switching to an audio only source, this method is called to broadcast * a setSystemAudioMode on message to the HDMI CEC system without querying Active Source or * TV supporting System Audio Control or not. This is to get volume control passthrough * from STB even if TV does not support it. * * @hide */ public void setSystemAudioModeOnForAudioOnlySource() { try { mService.setSystemAudioModeOnForAudioOnlySource(); } catch (RemoteException e) { Log.d(TAG, "Failed to set System Audio Mode on for Audio Only source"); } } }