| /* |
| * Copyright (C) 2020 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.car.audio; |
| |
| import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; |
| |
| import android.annotation.NonNull; |
| import android.car.Car; |
| import android.car.media.CarAudioManager; |
| import android.content.pm.PackageManager; |
| import android.media.AudioFocusInfo; |
| import android.media.AudioManager; |
| import android.os.Bundle; |
| import android.util.IndentingPrintWriter; |
| |
| import com.android.car.audio.CarAudioContext.AudioContext; |
| import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Objects; |
| |
| final class FocusEntry { |
| private final AudioFocusInfo mAudioFocusInfo; |
| private final int mAudioContext; |
| |
| private final List<FocusEntry> mBlockers; |
| private final PackageManager mPackageManager; |
| private boolean mIsDucked; |
| |
| FocusEntry(@NonNull AudioFocusInfo audioFocusInfo, @AudioContext int context, |
| @NonNull PackageManager packageManager) { |
| Objects.requireNonNull(audioFocusInfo, "AudioFocusInfo cannot be null"); |
| Objects.requireNonNull(packageManager, "PackageManager cannot be null"); |
| mAudioFocusInfo = audioFocusInfo; |
| mAudioContext = context; |
| mBlockers = new ArrayList<>(); |
| mPackageManager = packageManager; |
| } |
| |
| @AudioContext |
| int getAudioContext() { |
| return mAudioContext; |
| } |
| |
| AudioFocusInfo getAudioFocusInfo() { |
| return mAudioFocusInfo; |
| } |
| |
| boolean isUnblocked() { |
| return mBlockers.isEmpty(); |
| } |
| |
| void addBlocker(FocusEntry blocker) { |
| mBlockers.add(blocker); |
| } |
| |
| void removeBlocker(FocusEntry blocker) { |
| mBlockers.remove(blocker); |
| } |
| |
| String getClientId() { |
| return mAudioFocusInfo.getClientId(); |
| } |
| |
| boolean isDucked() { |
| return mIsDucked; |
| } |
| |
| void setDucked(boolean ducked) { |
| mIsDucked = ducked; |
| } |
| |
| boolean wantsPauseInsteadOfDucking() { |
| return (mAudioFocusInfo.getFlags() & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) |
| != 0; |
| } |
| |
| boolean receivesDuckEvents() { |
| Bundle bundle = mAudioFocusInfo.getAttributes().getBundle(); |
| |
| if (bundle == null) { |
| return false; |
| } |
| |
| if (!bundle.getBoolean(CarAudioManager.AUDIOFOCUS_EXTRA_RECEIVE_DUCKING_EVENTS)) { |
| return false; |
| } |
| |
| return (mPackageManager.checkPermission( |
| Car.PERMISSION_RECEIVE_CAR_AUDIO_DUCKING_EVENTS, |
| mAudioFocusInfo.getPackageName()) |
| == PackageManager.PERMISSION_GRANTED); |
| } |
| |
| @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) |
| public void dump(IndentingPrintWriter writer) { |
| writer.printf("%s - %s\n", getClientId(), mAudioFocusInfo.getAttributes().usageToString()); |
| writer.increaseIndent(); |
| // Prints in single line |
| writer.printf("Receives Duck Events: %b, ", receivesDuckEvents()); |
| writer.printf("Wants Pause Instead of Ducking: %b, ", wantsPauseInsteadOfDucking()); |
| writer.printf("Is Ducked: %b\n", isDucked()); |
| writer.decreaseIndent(); |
| } |
| } |