• 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.systemui.car.statusicon.ui;
18 
19 import static android.car.media.CarAudioManager.INVALID_AUDIO_ZONE;
20 import static android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE;
21 import static android.media.AudioAttributes.USAGE_MEDIA;
22 
23 import android.car.Car;
24 import android.car.CarOccupantZoneManager;
25 import android.car.media.CarAudioManager;
26 import android.content.Context;
27 import android.content.res.Resources;
28 import android.graphics.drawable.Drawable;
29 
30 import androidx.annotation.Nullable;
31 import androidx.annotation.VisibleForTesting;
32 
33 import com.android.systemui.R;
34 import com.android.systemui.car.CarServiceProvider;
35 import com.android.systemui.car.statusicon.StatusIconView;
36 import com.android.systemui.car.statusicon.StatusIconViewController;
37 import com.android.systemui.car.systembar.element.CarSystemBarElementStateController;
38 import com.android.systemui.car.systembar.element.CarSystemBarElementStatusBarDisableController;
39 import com.android.systemui.dagger.qualifiers.Main;
40 import com.android.systemui.settings.UserTracker;
41 
42 import dagger.assisted.Assisted;
43 import dagger.assisted.AssistedFactory;
44 import dagger.assisted.AssistedInject;
45 
46 /**
47  * A controller for media volume status icon in the QC entry point area.
48  */
49 public class MediaVolumeStatusIconController extends StatusIconViewController {
50 
51     private final Context mContext;
52     private final Resources mResources;
53     private final UserTracker mUserTracker;
54     private final CarServiceProvider mCarServiceProvider;
55 
56     private CarAudioManager mCarAudioManager;
57     private Drawable mMediaVolumeStatusIconDrawable;
58     private int mMaxMediaVolume;
59     private int mMinMediaVolume;
60     private int mGroupId;
61     private int mZoneId;
62 
63     private final UserTracker.Callback mUserTrackerCallback = new UserTracker.Callback() {
64         @Override
65         public void onUserChanged(int newUser, Context userContext) {
66             updateStatus(mZoneId, mGroupId);
67         }
68     };
69 
70     private final CarServiceProvider.CarServiceOnConnectedListener mCarOnConnectedListener =
71             new CarServiceProvider.CarServiceOnConnectedListener() {
72                 @Override
73                 public void onConnected(Car car) {
74                     CarOccupantZoneManager.OccupantZoneInfo occupantZoneInfo = null;
75                     CarOccupantZoneManager carOccupantZoneManager =
76                             (CarOccupantZoneManager) car.getCarManager(
77                                     Car.CAR_OCCUPANT_ZONE_SERVICE);
78                     if (carOccupantZoneManager != null) {
79                         occupantZoneInfo = carOccupantZoneManager.getMyOccupantZone();
80                     }
81                     mZoneId = PRIMARY_AUDIO_ZONE;
82                     if (occupantZoneInfo != null) {
83                         int occupantAudioId = carOccupantZoneManager
84                                 .getAudioZoneIdForOccupant(occupantZoneInfo);
85                         if (occupantAudioId != INVALID_AUDIO_ZONE) {
86                             mZoneId = occupantAudioId;
87                         }
88                     }
89 
90                     mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE);
91 
92                     if (mCarAudioManager != null) {
93                         mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback);
94                         mGroupId = mCarAudioManager.getVolumeGroupIdForUsage(mZoneId, USAGE_MEDIA);
95                         mMaxMediaVolume = mCarAudioManager.getGroupMaxVolume(mZoneId, mGroupId);
96                         mMinMediaVolume = mCarAudioManager.getGroupMinVolume(mZoneId, mGroupId);
97                     }
98                     updateStatus(mZoneId, mGroupId);
99                 }
100             };
101 
102     @AssistedInject
MediaVolumeStatusIconController( @ssisted StatusIconView view, CarSystemBarElementStatusBarDisableController disableController, CarSystemBarElementStateController stateController, Context context, UserTracker userTracker, @Main Resources resources, CarServiceProvider carServiceProvider)103     MediaVolumeStatusIconController(
104             @Assisted StatusIconView view,
105             CarSystemBarElementStatusBarDisableController disableController,
106             CarSystemBarElementStateController stateController,
107             Context context,
108             UserTracker userTracker,
109             @Main Resources resources,
110             CarServiceProvider carServiceProvider) {
111         super(view, disableController, stateController);
112         mContext = context;
113         mResources = resources;
114         mUserTracker = userTracker;
115         mCarServiceProvider = carServiceProvider;
116     }
117 
118     @AssistedFactory
119     public interface Factory extends
120             StatusIconViewController.Factory<MediaVolumeStatusIconController> {
121     }
122 
123     @Override
onViewAttached()124     protected void onViewAttached() {
125         super.onViewAttached();
126         mUserTracker.addCallback(mUserTrackerCallback, mContext.getMainExecutor());
127         mCarServiceProvider.addListener(mCarOnConnectedListener);
128     }
129 
130     @Override
onViewDetached()131     protected void onViewDetached() {
132         super.onViewDetached();
133         mCarServiceProvider.removeListener(mCarOnConnectedListener);
134         mUserTracker.removeCallback(mUserTrackerCallback);
135         if (mCarAudioManager != null) {
136             mCarAudioManager.unregisterCarVolumeCallback(mVolumeChangeCallback);
137         }
138     }
139 
140     @Override
updateStatus()141     protected void updateStatus() {
142         setIconDrawableToDisplay(mMediaVolumeStatusIconDrawable);
143         onStatusUpdated();
144     }
145 
updateStatus(int zoneId, int groupId)146     private void updateStatus(int zoneId, int groupId) {
147         if (mZoneId != zoneId || mGroupId != groupId) {
148             return;
149         }
150         if (mCarAudioManager != null) {
151             int currentMediaVolumeLevel = mCarAudioManager.getGroupVolume(mZoneId, mGroupId);
152             if (currentMediaVolumeLevel == mMinMediaVolume) {
153                 mMediaVolumeStatusIconDrawable = mResources.getDrawable(
154                         R.drawable.car_ic_media_volume_off, mContext.getTheme());
155             } else if (currentMediaVolumeLevel <= (mMaxMediaVolume / 2)) {
156                 mMediaVolumeStatusIconDrawable = mResources.getDrawable(
157                         R.drawable.car_ic_media_volume_down, mContext.getTheme());
158             } else {
159                 mMediaVolumeStatusIconDrawable = mResources.getDrawable(
160                         R.drawable.car_ic_media_volume_up, mContext.getTheme());
161             }
162             updateStatus();
163         }
164     }
165 
166     private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback =
167             new CarAudioManager.CarVolumeCallback() {
168                 @Override
169                 public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
170                     updateStatus(zoneId, groupId);
171                 }
172 
173                 @Override
174                 public void onMasterMuteChanged(int zoneId, int flags) {
175                     // Mute is not being used yet
176                 }
177 
178                 @Override
179                 public void onGroupMuteChanged(int zoneId, int groupId, int flags) {
180                     updateStatus(zoneId, groupId);
181                 }
182             };
183 
184     /**
185      * Get the current media volume status icon in the QC entry point area.
186      */
187     @VisibleForTesting
188     @Nullable
getMediaVolumeStatusIconDrawable()189     Drawable getMediaVolumeStatusIconDrawable() {
190         return mMediaVolumeStatusIconDrawable;
191     }
192 }
193