• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.google.android.car.kitchensink.volume;
17 
18 import android.car.Car;
19 import android.car.media.CarAudioManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.ServiceConnection;
23 import android.media.AudioManager;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.Message;
28 import android.util.Log;
29 import android.util.SparseIntArray;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.ListView;
34 import android.widget.SeekBar;
35 
36 import androidx.annotation.Nullable;
37 import androidx.fragment.app.Fragment;
38 
39 import com.google.android.car.kitchensink.R;
40 
41 public class VolumeTestFragment extends Fragment {
42     private static final String TAG = "CarVolumeTest";
43     private static final int MSG_VOLUME_CHANGED = 0;
44     private static final int MSG_REQUEST_FOCUS = 1;
45     private static final int MSG_FOCUS_CHANGED= 2;
46 
47     private AudioManager mAudioManager;
48     private VolumeAdapter mAdapter;
49 
50     private CarAudioManager mCarAudioManager;
51     private Car mCar;
52 
53     private SeekBar mFader;
54     private SeekBar mBalance;
55 
56     private final Handler mHandler = new VolumeHandler();
57 
58     private class VolumeHandler extends Handler {
59         private AudioFocusListener mFocusListener;
60 
61         @Override
handleMessage(Message msg)62         public void handleMessage(Message msg) {
63             switch (msg.what) {
64                 case MSG_VOLUME_CHANGED:
65                     initVolumeInfo();
66                     break;
67                 case MSG_REQUEST_FOCUS:
68                     int groupId = msg.arg1;
69                     if (mFocusListener != null) {
70                         mAudioManager.abandonAudioFocus(mFocusListener);
71                         mVolumeInfos[mGroupIdIndexMap.get(groupId)].mHasFocus = false;
72                         mAdapter.notifyDataSetChanged();
73                     }
74 
75                     mFocusListener = new AudioFocusListener(groupId);
76                     mAudioManager.requestAudioFocus(mFocusListener, groupId,
77                             AudioManager.AUDIOFOCUS_GAIN);
78                     break;
79                 case MSG_FOCUS_CHANGED:
80                     int focusGroupId = msg.arg1;
81                     mVolumeInfos[mGroupIdIndexMap.get(focusGroupId)].mHasFocus = true;
82                     mAdapter.refreshVolumes(mVolumeInfos);
83                     break;
84 
85             }
86         }
87     }
88 
89     private VolumeInfo[] mVolumeInfos = new VolumeInfo[0];
90     private SparseIntArray mGroupIdIndexMap = new SparseIntArray();
91 
92     private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
93         private final int mGroupId;
AudioFocusListener(int groupId)94         public AudioFocusListener(int groupId) {
95             mGroupId = groupId;
96         }
97         @Override
onAudioFocusChange(int focusChange)98         public void onAudioFocusChange(int focusChange) {
99             if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
100                 mHandler.sendMessage(mHandler.obtainMessage(MSG_FOCUS_CHANGED, mGroupId, 0));
101             } else {
102                 Log.e(TAG, "Audio focus request failed");
103             }
104         }
105     }
106 
107     public static class VolumeInfo {
108         public int mGroupId;
109         public String mId;
110         public String mMax;
111         public String mCurrent;
112         public boolean mHasFocus;
113     }
114 
115     private final ServiceConnection mCarConnectionCallback =
116             new ServiceConnection() {
117                 @Override
118                 public void onServiceConnected(ComponentName name, IBinder binder) {
119                     Log.d(TAG, "Connected to Car Service");
120                     mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
121                     initVolumeInfo();
122                 }
123 
124                 @Override
125                 public void onServiceDisconnected(ComponentName name) {
126                     Log.d(TAG, "Disconnect from Car Service");
127                 }
128             };
129 
130     @Override
onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)131     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
132                              @Nullable Bundle savedInstanceState) {
133         View v = inflater.inflate(R.layout.volume_test, container, false);
134 
135         ListView volumeListView = v.findViewById(R.id.volume_list);
136         mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
137 
138         mAdapter = new VolumeAdapter(getContext(), R.layout.volume_item, mVolumeInfos, this);
139         volumeListView.setAdapter(mAdapter);
140 
141         v.findViewById(R.id.refresh).setOnClickListener((view) -> initVolumeInfo());
142 
143         final SeekBar.OnSeekBarChangeListener seekListener = new SeekBar.OnSeekBarChangeListener() {
144             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
145                 final float percent = (progress - 100) / 100.0f;
146                 if (seekBar.getId() == R.id.fade_bar) {
147                     mCarAudioManager.setFadeTowardFront(percent);
148                 } else {
149                     mCarAudioManager.setBalanceTowardRight(percent);
150                 }
151             }
152 
153             public void onStartTrackingTouch(SeekBar seekBar) {}
154 
155             public void onStopTrackingTouch(SeekBar seekBar) {}
156         };
157 
158         mFader = v.findViewById(R.id.fade_bar);
159         mFader.setOnSeekBarChangeListener(seekListener);
160 
161         mBalance = v.findViewById(R.id.balance_bar);
162         mBalance.setOnSeekBarChangeListener(seekListener);
163 
164         mCar = Car.createCar(getActivity(), mCarConnectionCallback);
165         mCar.connect();
166         return v;
167     }
168 
adjustVolumeByOne(int groupId, boolean up)169     public void adjustVolumeByOne(int groupId, boolean up) {
170         if (mCarAudioManager == null) {
171             Log.e(TAG, "CarAudioManager is null");
172             return;
173         }
174         int current = mCarAudioManager.getGroupVolume(groupId);
175         int volume = current + (up ? 1 : -1);
176         mCarAudioManager.setGroupVolume(groupId, volume,
177                 AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
178         Log.d(TAG, "Set group " + groupId + " volume " + volume);
179     }
180 
requestFocus(int groupId)181     public void requestFocus(int groupId) {
182         mHandler.sendMessage(mHandler.obtainMessage(MSG_REQUEST_FOCUS, groupId));
183     }
184 
initVolumeInfo()185     private void initVolumeInfo() {
186         int volumeGroupCount = mCarAudioManager.getVolumeGroupCount();
187         mVolumeInfos = new VolumeInfo[volumeGroupCount + 1];
188         mGroupIdIndexMap.clear();
189         mVolumeInfos[0] = new VolumeInfo();
190         mVolumeInfos[0].mId = "Group id";
191         mVolumeInfos[0].mCurrent = "Current";
192         mVolumeInfos[0].mMax = "Max";
193 
194         int i = 1;
195         for (int groupId = 0; groupId < volumeGroupCount; groupId++) {
196             mVolumeInfos[i] = new VolumeInfo();
197             mVolumeInfos[i].mGroupId = groupId;
198             mGroupIdIndexMap.put(groupId, i);
199             mVolumeInfos[i].mId = String.valueOf(groupId);
200 
201 
202             int current = mCarAudioManager.getGroupVolume(groupId);
203             int max = mCarAudioManager.getGroupMaxVolume(groupId);
204             mVolumeInfos[i].mCurrent = String.valueOf(current);
205             mVolumeInfos[i].mMax = String.valueOf(max);
206 
207             Log.d(TAG, groupId + " max: " + mVolumeInfos[i].mMax + " current: "
208                     + mVolumeInfos[i].mCurrent);
209             i++;
210         }
211         mAdapter.refreshVolumes(mVolumeInfos);
212     }
213 
214     @Override
onDestroy()215     public void onDestroy() {
216         if (mCar != null) {
217             mCar.disconnect();
218         }
219         super.onDestroy();
220     }
221 }
222