• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.car.audio;
18 
19 import android.car.builtin.util.Slogf;
20 import android.car.media.CarVolumeGroupEvent;
21 import android.car.media.ICarVolumeEventCallback;
22 import android.os.Handler;
23 import android.os.HandlerThread;
24 import android.os.RemoteCallbackList;
25 import android.os.RemoteException;
26 
27 import com.android.car.CarLog;
28 import com.android.car.CarServiceUtils;
29 import com.android.internal.annotations.GuardedBy;
30 
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Objects;
34 import java.util.Set;
35 
36 /**
37  * Manages callbacks for volume events
38  */
39 final class CarVolumeEventHandler extends RemoteCallbackList<ICarVolumeEventCallback> {
40     private static final String REQUEST_HANDLER_THREAD_NAME = "CarVolumeCallback";
41 
42     private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
43             REQUEST_HANDLER_THREAD_NAME);
44     private final Handler mHandler = new Handler(mHandlerThread.getLooper());
45 
46     private final Object mLock = new Object();
47     @GuardedBy("mLock")
48     private final Set<Integer> mUids = new HashSet<Integer>();
49 
release()50     void release() {
51         synchronized (mLock) {
52             mUids.clear();
53         }
54     }
55 
registerCarVolumeEventCallback(ICarVolumeEventCallback callback, int uid)56     public void registerCarVolumeEventCallback(ICarVolumeEventCallback callback, int uid) {
57         Objects.requireNonNull(callback, "Car volume  callback can not be null");
58 
59         synchronized (mLock) {
60             register(callback, uid);
61             mUids.add(uid);
62         }
63     }
64 
unregisterCarVolumeEventCallback(ICarVolumeEventCallback callback, int uid)65     public void unregisterCarVolumeEventCallback(ICarVolumeEventCallback callback, int uid) {
66         Objects.requireNonNull(callback, "Car volume  callback can not be null");
67 
68         synchronized (mLock) {
69             unregister(callback);
70             mUids.remove(uid);
71         }
72     }
73 
checkIfUidIsRegistered(int uid)74     boolean checkIfUidIsRegistered(int uid) {
75         synchronized (mLock) {
76             return mUids.contains(uid);
77         }
78     }
79 
onVolumeGroupEvent(List<CarVolumeGroupEvent> events)80     void onVolumeGroupEvent(List<CarVolumeGroupEvent> events) {
81         mHandler.post(() -> {
82             int count = beginBroadcast();
83             for (int index = 0; index < count; index++) {
84                 try {
85                     ICarVolumeEventCallback callback = getBroadcastItem(index);
86                     callback.onVolumeGroupEvent(List.copyOf(events));
87                 } catch (RemoteException e) {
88                     Slogf.e(CarLog.TAG_AUDIO, "Failed to callback onVolumeGroupEvent", e);
89                 }
90             }
91             finishBroadcast();
92         });
93     }
94 
onMasterMuteChanged(int zoneId, int flags)95     void onMasterMuteChanged(int zoneId, int flags) {
96         mHandler.post(() -> {
97             int count = beginBroadcast();
98             for (int index = 0; index < count; index++) {
99                 try {
100                     ICarVolumeEventCallback callback = getBroadcastItem(index);
101                     callback.onMasterMuteChanged(zoneId, flags);
102                 } catch (RemoteException e) {
103                     Slogf.e(CarLog.TAG_AUDIO, "Failed to callback onMasterMuteChanged", e);
104                 }
105             }
106             finishBroadcast();
107         });
108     }
109 
110     @Override
onCallbackDied(ICarVolumeEventCallback callback, Object cookie)111     public void onCallbackDied(ICarVolumeEventCallback callback, Object cookie) {
112         int uid = (int) cookie;
113         // when client dies, clean up obsolete user-id from the list
114         synchronized (mLock) {
115             mUids.remove(uid);
116         }
117     }
118 }
119