1 /*
2  * Copyright (C) 2020 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.google.android.car.kitchensink.audio;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.car.Car;
22 import android.car.media.CarAudioManager;
23 import android.content.Context;
24 import android.media.AudioManager;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.util.Log;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 
33 import androidx.fragment.app.Fragment;
34 import androidx.viewpager.widget.ViewPager;
35 
36 import com.google.android.car.kitchensink.R;
37 import com.google.android.material.tabs.TabLayout;
38 
39 import java.util.List;
40 
41 public class CarAudioInputTestFragment extends Fragment {
42 
43     private static final String TAG = "CAR.AUDIO.INPUT.KS";
44     private static final boolean DEBUG = true;
45 
46 
47     private Handler mHandler;
48     private Context mContext;
49 
50     private Car mCar;
51     private AudioManager mAudioManager;
52     private CarAudioManager mCarAudioManager;
53     private TabLayout mZonesTabLayout;
54     private CarAudioZoneTabAdapter mInputAudioZoneAdapter;
55     private ViewPager mViewPager;
56 
connectCar()57     private void connectCar() {
58         mContext = getContext();
59         mHandler = new Handler(Looper.getMainLooper());
60         mCar = Car.createCar(mContext, /* handler= */ null,
61                 Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER, mCarServiceLifecycleListener);
62     }
63 
64     private Car.CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
65         if (!ready) {
66             if (DEBUG) {
67                 Log.d(TAG, "Disconnect from Car Service");
68             }
69             return;
70         }
71         if (DEBUG) {
72             Log.d(TAG, "Connected to Car Service");
73         }
74         mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE);
75 
76         mAudioManager = mContext.getSystemService(AudioManager.class);
77     };
78 
79 
80     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle)81     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
82         Log.i(TAG, "onCreateView");
83         View view = inflater.inflate(R.layout.audio_input, container, false);
84         connectCar();
85         return view;
86     }
87 
88     @Override
onViewCreated(@onNull View view, @Nullable Bundle savedInstanceState)89     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
90         Log.i(TAG, "onViewCreated ");
91         mZonesTabLayout = view.findViewById(R.id.zones_input_tab);
92         mViewPager = view.findViewById(R.id.zones_input_view_pager);
93 
94         mInputAudioZoneAdapter = new CarAudioZoneTabAdapter(getChildFragmentManager());
95         mViewPager.setAdapter(mInputAudioZoneAdapter);
96         initInputInfo();
97         mZonesTabLayout.setupWithViewPager(mViewPager);
98     }
99 
100     @Override
onDestroyView()101     public void onDestroyView() {
102         Log.i(TAG, "onDestroyView");
103 
104         if (mCar != null && mCar.isConnected()) {
105             mCar.disconnect();
106             mCar = null;
107         }
108         super.onDestroyView();
109     }
110 
initInputInfo()111     private void initInputInfo() {
112         if (!mCarAudioManager.isAudioFeatureEnabled(
113                 CarAudioManager.AUDIO_FEATURE_DYNAMIC_ROUTING)) {
114             return;
115         }
116         List<Integer> audioZoneList = mCarAudioManager.getAudioZoneIds();
117         for (int audioZoneId : audioZoneList) {
118             if (mCarAudioManager.getInputDevicesForZoneId(audioZoneId).isEmpty()) {
119                 if (DEBUG) {
120                     Log.d(TAG, "Audio Zone " + audioZoneId + " has no input devices");
121                 }
122                 continue;
123             }
124             addAudioZoneInputDevices(audioZoneId);
125         }
126         mInputAudioZoneAdapter.notifyDataSetChanged();
127     }
128 
addAudioZoneInputDevices(int audioZoneId)129     private void addAudioZoneInputDevices(int audioZoneId) {
130         String title = "Audio Zone " + audioZoneId;
131         if (DEBUG) {
132             Log.d(TAG, title + " adding devices");
133         }
134         CarAudioZoneInputFragment fragment = new CarAudioZoneInputFragment(audioZoneId,
135                 mCarAudioManager, mAudioManager);
136 
137         mZonesTabLayout.addTab(mZonesTabLayout.newTab().setText(title));
138         mInputAudioZoneAdapter.addFragment(fragment, title);
139     }
140 
getAudioInputLogTag(Class clazz)141     static String getAudioInputLogTag(Class clazz) {
142         return TAG + clazz.getSimpleName();
143     }
144 }
145