WiredHeadsetManager.java revision c395e49e7b9aef59e5b4092945a8648f5adba3a0
16aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal/* 26aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * Copyright (C) 2014 The Android Open Source Project 36aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * 46aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License"); 56aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * you may not use this file except in compliance with the License. 66aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * You may obtain a copy of the License at 76aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * 86aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * http://www.apache.org/licenses/LICENSE-2.0 96aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * 106aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * Unless required by applicable law or agreed to in writing, software 116aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS, 126aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * See the License for the specific language governing permissions and 146aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal * limitations under the License. 156aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal */ 166aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom; 186aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 196aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.content.BroadcastReceiver; 206aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.content.Context; 216aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.content.Intent; 226aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.content.IntentFilter; 236aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.media.AudioManager; 246aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 259787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunnimport com.android.internal.util.IndentingPrintWriter; 269787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn 27a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shraunerimport java.util.Collections; 28a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shraunerimport java.util.Set; 29a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shraunerimport java.util.concurrent.ConcurrentHashMap; 30b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal 31b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal/** Listens for and caches headset state. */ 326aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalclass WiredHeadsetManager { 33b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal interface Listener { 34b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn); 35b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal } 36b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal 376aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal /** Receiver for wired headset plugged and unplugged events. */ 386aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal private class WiredHeadsetBroadcastReceiver extends BroadcastReceiver { 396aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal @Override 406aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal public void onReceive(Context context, Intent intent) { 416aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) { 42c395e49e7b9aef59e5b4092945a8648f5adba3a0Santos Cordon boolean isPluggedIn = mAudioManager.isWiredHeadsetOn(); 436aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal Log.v(WiredHeadsetManager.this, "ACTION_HEADSET_PLUG event, plugged in: %b", 446aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal isPluggedIn); 456aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal onHeadsetPluggedInChanged(isPluggedIn); 466aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 476aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 486aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 496aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 506aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal private final WiredHeadsetBroadcastReceiver mReceiver; 51c395e49e7b9aef59e5b4092945a8648f5adba3a0Santos Cordon private final AudioManager mAudioManager; 526aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal private boolean mIsPluggedIn; 53a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner /** 54a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 55a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner * load factor before resizing, 1 means we only expect a single thread to 56a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner * access the map so make only a single shard 57a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner */ 58a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner private final Set<Listener> mListeners = Collections.newSetFromMap( 59a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 606aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 61b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal WiredHeadsetManager(Context context) { 626aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal mReceiver = new WiredHeadsetBroadcastReceiver(); 636aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 64c395e49e7b9aef59e5b4092945a8648f5adba3a0Santos Cordon mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 65c395e49e7b9aef59e5b4092945a8648f5adba3a0Santos Cordon mIsPluggedIn = mAudioManager.isWiredHeadsetOn(); 666aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 676aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal // Register for misc other intent broadcasts. 686aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); 696aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal context.registerReceiver(mReceiver, intentFilter); 706aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 716aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 72b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal void addListener(Listener listener) { 73b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal mListeners.add(listener); 74b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal } 75b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal 76b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal void removeListener(Listener listener) { 77a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner if (listener != null) { 78a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner mListeners.remove(listener); 79a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner } 80b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal } 81b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal 826aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal boolean isPluggedIn() { 836aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal return mIsPluggedIn; 846aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 856aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 866aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal private void onHeadsetPluggedInChanged(boolean isPluggedIn) { 876aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal if (mIsPluggedIn != isPluggedIn) { 886aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal Log.v(this, "onHeadsetPluggedInChanged, mIsPluggedIn: %b -> %b", mIsPluggedIn, 896aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal isPluggedIn); 906aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal boolean oldIsPluggedIn = mIsPluggedIn; 916aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal mIsPluggedIn = isPluggedIn; 92b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal for (Listener listener : mListeners) { 93b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal listener.onWiredHeadsetPluggedInChanged(oldIsPluggedIn, mIsPluggedIn); 94b88795aadc636d14156791c2fc93af051d7e0d49Sailesh Nepal } 956aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 966aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 979787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn 989787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn /** 999787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn * Dumps the state of the {@link WiredHeadsetManager}. 1009787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn * 1019787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn * @param pw The {@code IndentingPrintWriter} to write the state to. 1029787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn */ 1039787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn public void dump(IndentingPrintWriter pw) { 1049787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn pw.println("mIsPluggedIn: " + mIsPluggedIn); 1059787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn } 1066aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal} 107