Loading core/java/android/view/WindowManagerPolicy.java +8 −0 Original line number Diff line number Diff line Loading @@ -901,6 +901,14 @@ public interface WindowManagerPolicy { */ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen); /** * Tell the policy that the jack switch has changed state. * @param whenNanos The time when the change occurred in uptime nanoseconds.. * @param switchCode Explains the Jack types * @param jackOpen True if the jacktype is now inserted. */ public void notifyJackSwitchChanged(long whenNanos, int switchCode, boolean jackOpen); /** * Tell the policy if anyone is requesting that keyguard not come on. * Loading policy/src/com/android/internal/policy/impl/PhoneWindowManager.java 100755 → 100644 +259 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,42 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; // Useful scan codes. //private static final int SW_LID = 0x00; private static final int SW_HEADPHONE_INSERT = 0x02; private static final int SW_MICROPHONE_INSERT = 0x04; //ToDo: This needs to be revisted once the kernel has support to report ANC event private static final int SW_ANC_INSERT = 0x08; private static final int SW_HEADSET_INSERT = (SW_HEADPHONE_INSERT|SW_MICROPHONE_INSERT); private static final int SW_ANC_HEADPHONE_INSERT = 0x10; private static final int SW_ANC_MICROPHONE_INSERT = 0x20; private static final int SW_ANC_HEADSET_INSERT = (SW_ANC_HEADPHONE_INSERT|SW_ANC_MICROPHONE_INSERT); private static final int BTN_MOUSE = 0x110; // Useful HeadSet codes... Same definition as WireAccessoryObserver.java private static int mHeadsetJackState = 0; private static boolean mIsAncOn = false; private static final int BIT_HEADSET = (1 << 0); private static final int BIT_HEADSET_SPEAKER_ONLY = (1 << 1); //Useful Headset codes... QC added definitions private static final int BIT_HEADSET_MIC_ONLY = (1 << 2); private static final int BIT_ANC_HEADSET = (1 << 3); private static final int BIT_ANC_HEADSET_SPEAKER_ONLY = (1 << 4); private static final int BIT_ANC_HEADSET_MIC_ONLY = (1 << 5); private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_SPEAKER_ONLY|BIT_HEADSET_MIC_ONLY | BIT_ANC_HEADSET|BIT_ANC_HEADSET_SPEAKER_ONLY|BIT_ANC_HEADSET_MIC_ONLY); private static final int BIT_HEADSET_NO_MIC = BIT_HEADSET_SPEAKER_ONLY; private static final int BIT_ANC_HEADSET_NO_MIC = BIT_ANC_HEADSET_SPEAKER_ONLY; private static final int ANC_HEADSETS_WITH_MIC = BIT_ANC_HEADSET; private static final int HEADSETS_WITH_MIC = BIT_HEADSET; private String mHeadsetName = "Headset"; private int mPrevHeadsetState = 0; private int mCurHeadsetState = 0; private boolean mHeadsetIntent = false; private final Object mHeadsetLock = new Object(); /** * These are the system UI flags that, when changing, can cause the layout * of the screen to change. Loading Loading @@ -3534,6 +3570,224 @@ public class PhoneWindowManager implements WindowManagerPolicy { setHdmiPlugged(!mHdmiPlugged); } /** {@inheritDoc} */ public void notifyJackSwitchChanged(long whenNanos, int switchCode, boolean switchState) { Slog.d(TAG,"notifyJackSwitchChanged(): switchCode "+switchCode+" switchState "+switchState); synchronized(mHeadsetLock) { if(switchCode == SW_ANC_INSERT) { if(switchState) { mIsAncOn = true; if((mHeadsetJackState & BIT_HEADSET) != 0) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET; } if((mHeadsetJackState & BIT_HEADSET_SPEAKER_ONLY) != 0) { mHeadsetJackState &= ~BIT_HEADSET_SPEAKER_ONLY; mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } if((mHeadsetJackState & BIT_HEADSET_MIC_ONLY) != 0) { mHeadsetJackState &= ~BIT_HEADSET_MIC_ONLY; mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } } else { mIsAncOn = false; if((mHeadsetJackState & BIT_ANC_HEADSET) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_HEADSET; } if((mHeadsetJackState & BIT_ANC_HEADSET_SPEAKER_ONLY) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET_SPEAKER_ONLY; mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } if((mHeadsetJackState & BIT_ANC_HEADSET_MIC_ONLY) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET_MIC_ONLY; mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } } } else if ( switchCode == SW_HEADPHONE_INSERT) { if (switchState) { if(mIsAncOn) { mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } else { mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } } else if( (mHeadsetJackState & BIT_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } else if( (mHeadsetJackState & BIT_ANC_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } else { if(mIsAncOn) { mHeadsetJackState &= ~BIT_ANC_HEADSET_SPEAKER_ONLY; } else { mHeadsetJackState &= ~BIT_HEADSET_SPEAKER_ONLY; } } } else if ( switchCode == SW_MICROPHONE_INSERT) { if (switchState) { if(mIsAncOn) { mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } else { mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } } else if( (mHeadsetJackState & BIT_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } else if( (mHeadsetJackState & BIT_ANC_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } else { if(mIsAncOn) { mHeadsetJackState &= ~BIT_ANC_HEADSET_MIC_ONLY; } else { mHeadsetJackState &= ~BIT_HEADSET_MIC_ONLY; } } } if( mHeadsetJackState == SW_HEADSET_INSERT ) { // If both Speaker and Mic bits are set, remove them and // set Headset bit to indicate Headset insertion mHeadsetJackState = BIT_HEADSET; } if( mHeadsetJackState == SW_ANC_HEADSET_INSERT ) { mHeadsetJackState = BIT_ANC_HEADSET; } update(); } // synchronized(mHeadsetLock) } private synchronized final void update() { // Retain only relevant bits int headsetState = mHeadsetJackState & SUPPORTED_HEADSETS; // Set default delay to 10msec to allow all the events to reach before sending intent int delay = 10; // reject all suspect transitions: only accept state changes from: // - a: 0 heaset to 1 headset // - b: 1 headset to 0 headset if (mCurHeadsetState == headsetState) { return; } if (headsetState == 0) { Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY); mContext.sendBroadcast(intent); // It can take hundreds of ms flush the audio pipeline after // apps pause audio playback, but audio route changes are // immediate, so delay the route change by 1000ms. // This could be improved once the audio sub-system provides an // interface to clear the audio pipeline. delay = 1000; } else { // Insert the same delay for headset connection so that the connection event is not // broadcast before the disconnection event in case of fast removal/insertion if ( mIntentHandler.hasMessages(0)) { delay = 1000; } } mBroadcastWakeLock.acquire(); Slog.d(TAG,"update(): sending Message to IntentHander with delay of "+delay); mIntentHandler.sendMessageDelayed( mIntentHandler.obtainMessage(0, mHeadsetName), delay); } private synchronized final void sendIntents(String headsetName) { Slog.d(TAG,"sendIntents(): mHeadsetJackState "+mHeadsetJackState+" mCurHeadsetState "+mCurHeadsetState+" mPrevHeadsetState "+mPrevHeadsetState); int headsetState; synchronized(mHeadsetLock) { headsetState = mHeadsetJackState & SUPPORTED_HEADSETS; if (mCurHeadsetState == headsetState) { return; } mPrevHeadsetState = mCurHeadsetState; mCurHeadsetState = headsetState; } int allHeadsets = SUPPORTED_HEADSETS; //Handle unplug events first and then handle plug-in events for (int curHeadset = 1; curHeadset < SUPPORTED_HEADSETS; curHeadset <<= 1) { if (((headsetState & curHeadset) == 0) && ((mPrevHeadsetState & curHeadset) == curHeadset)) { if ((curHeadset & allHeadsets) != 0) { sendIntent(curHeadset, headsetState, mPrevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } for (int curHeadset = 1; curHeadset < SUPPORTED_HEADSETS; curHeadset <<= 1) { if (((headsetState & curHeadset) == curHeadset) && ((mPrevHeadsetState & curHeadset) == 0)) { if ((curHeadset & allHeadsets) != 0) { sendIntent(curHeadset, headsetState, mPrevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } } private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { // Pack up the values and broadcast them to everyone int state = 0; int device = 0; if ((headset & BIT_HEADSET) != 0) { device = AudioManager.DEVICE_OUT_WIRED_HEADSET; } else if ((headset & BIT_HEADSET_SPEAKER_ONLY) != 0) { device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE; } else if ((headset & BIT_HEADSET_MIC_ONLY ) != 0) { device = 0; } else if ((headset & BIT_ANC_HEADSET) != 0) { device = 0;//AudioManager.DEVICE_OUT_ANC_HEADSET; } else if ((headset & BIT_ANC_HEADSET_SPEAKER_ONLY) != 0) { device = 0;//AudioManager.DEVICE_OUT_ANC_HEADPHONE; } else if ((headset & BIT_ANC_HEADSET_MIC_ONLY) != 0) { device = 0; } else { Slog.e(TAG, "setDeviceState() invalid headset type: "+headset); return; } if ((headsetState & headset) != 0) { state = 1; } else { state = 0; } if (mSystemBooted) { final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); if (am == null) { Log.e(TAG, "sendIntent: couldn't get AudioManager reference"); return; } am.setWiredDeviceConnectionState(device, state, headsetName); } else { Slog.d(TAG,"system not booted yet, call setWiredDeviceConnectionState later"); } } } private final Handler mIntentHandler = new Handler() { @Override public void handleMessage(Message msg) { Slog.d(TAG,"Headset detect: Inside handleMessage() for IntentHandler" + (String)msg.obj); if (mSystemBooted) { sendIntents((String)msg.obj); mBroadcastWakeLock.release(); } else { Log.e(TAG, "system not booted yet, send headset intent later"); mHeadsetIntent = true; mHeadsetName = (String)msg.obj; } } }; /** * @return Whether music is being played right now. */ Loading Loading @@ -4471,6 +4725,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void systemBooted() { synchronized (mLock) { mSystemBooted = true; if (mHeadsetIntent) { Log.e(TAG, "send headset intent after system booted"); sendIntents(mHeadsetName); mBroadcastWakeLock.release(); } } } Loading services/input/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ ifeq ($(BOARD_USE_LEGACY_TRACKPAD),true) LOCAL_CFLAGS += -DLEGACY_TRACKPAD endif ifeq ($(BOARD_USES_ALSA_AUDIO),true) LOCAL_CFLAGS += -DALSA_HEADSET_DETECTION endif LOCAL_MODULE:= libinput LOCAL_MODULE_TAGS := optional Loading services/input/EventHub.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ EventHub::EventHub(void) : mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mNeedToSendHeadPhoneEvent(false), mNeedToSendMicroPhoneEvent(false), mHeadsetDeviceId(-1), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); Loading Loading @@ -693,6 +694,22 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz event->type = DEVICE_ADDED; event += 1; mNeedToSendFinishedDeviceScan = true; #ifdef ALSA_HEADSET_DETECTION if(device->classes == INPUT_DEVICE_CLASS_SWITCH) { mLock.unlock(); int state = getSwitchState(device->id, SW_HEADPHONE_INSERT); if(state > 0) { mNeedToSendHeadPhoneEvent = true; } state = getSwitchState(device->id, SW_MICROPHONE_INSERT); mLock.lock(); if(state > 0) { mNeedToSendMicroPhoneEvent = true; } mHeadsetDeviceId = device->id; } #endif if (--capacity == 0) { break; } Loading @@ -708,6 +725,33 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz } } #ifdef ALSA_HEADSET_DETECTION if(mNeedToSendHeadPhoneEvent) { event->type = EV_SW; event->code = SW_HEADPHONE_INSERT; event->value = 1; event->deviceId = mHeadsetDeviceId; event->when = systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendHeadPhoneEvent = false; event += 1; if (--capacity == 0) { break; } } if(mNeedToSendMicroPhoneEvent) { event->type = EV_SW; event->code = SW_MICROPHONE_INSERT; event->value = 1; event->deviceId = mHeadsetDeviceId; event->when = systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendMicroPhoneEvent = false; event += 1; if (--capacity == 0) { break; } } #endif // Grab the next input event. bool deviceChanged = false; while (mPendingEventIndex < mPendingEventCount) { Loading Loading @@ -1039,6 +1083,8 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { // See if this is a keyboard. Ignore everything in the button range except for // joystick and gamepad buttons which are handled like keyboards for the most part. bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), sizeof_bit_array(BTN_9)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK), sizeof_bit_array(KEY_MAX + 1)); bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), Loading services/input/EventHub.h +3 −0 Original line number Diff line number Diff line Loading @@ -389,6 +389,9 @@ private: bool mNeedToSendFinishedDeviceScan; bool mNeedToReopenDevices; bool mNeedToScanDevices; bool mNeedToSendHeadPhoneEvent; bool mNeedToSendMicroPhoneEvent; int mHeadsetDeviceId; Vector<String8> mExcludedDevices; int mEpollFd; Loading Loading
core/java/android/view/WindowManagerPolicy.java +8 −0 Original line number Diff line number Diff line Loading @@ -901,6 +901,14 @@ public interface WindowManagerPolicy { */ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen); /** * Tell the policy that the jack switch has changed state. * @param whenNanos The time when the change occurred in uptime nanoseconds.. * @param switchCode Explains the Jack types * @param jackOpen True if the jacktype is now inserted. */ public void notifyJackSwitchChanged(long whenNanos, int switchCode, boolean jackOpen); /** * Tell the policy if anyone is requesting that keyguard not come on. * Loading
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java 100755 → 100644 +259 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,42 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; // Useful scan codes. //private static final int SW_LID = 0x00; private static final int SW_HEADPHONE_INSERT = 0x02; private static final int SW_MICROPHONE_INSERT = 0x04; //ToDo: This needs to be revisted once the kernel has support to report ANC event private static final int SW_ANC_INSERT = 0x08; private static final int SW_HEADSET_INSERT = (SW_HEADPHONE_INSERT|SW_MICROPHONE_INSERT); private static final int SW_ANC_HEADPHONE_INSERT = 0x10; private static final int SW_ANC_MICROPHONE_INSERT = 0x20; private static final int SW_ANC_HEADSET_INSERT = (SW_ANC_HEADPHONE_INSERT|SW_ANC_MICROPHONE_INSERT); private static final int BTN_MOUSE = 0x110; // Useful HeadSet codes... Same definition as WireAccessoryObserver.java private static int mHeadsetJackState = 0; private static boolean mIsAncOn = false; private static final int BIT_HEADSET = (1 << 0); private static final int BIT_HEADSET_SPEAKER_ONLY = (1 << 1); //Useful Headset codes... QC added definitions private static final int BIT_HEADSET_MIC_ONLY = (1 << 2); private static final int BIT_ANC_HEADSET = (1 << 3); private static final int BIT_ANC_HEADSET_SPEAKER_ONLY = (1 << 4); private static final int BIT_ANC_HEADSET_MIC_ONLY = (1 << 5); private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_SPEAKER_ONLY|BIT_HEADSET_MIC_ONLY | BIT_ANC_HEADSET|BIT_ANC_HEADSET_SPEAKER_ONLY|BIT_ANC_HEADSET_MIC_ONLY); private static final int BIT_HEADSET_NO_MIC = BIT_HEADSET_SPEAKER_ONLY; private static final int BIT_ANC_HEADSET_NO_MIC = BIT_ANC_HEADSET_SPEAKER_ONLY; private static final int ANC_HEADSETS_WITH_MIC = BIT_ANC_HEADSET; private static final int HEADSETS_WITH_MIC = BIT_HEADSET; private String mHeadsetName = "Headset"; private int mPrevHeadsetState = 0; private int mCurHeadsetState = 0; private boolean mHeadsetIntent = false; private final Object mHeadsetLock = new Object(); /** * These are the system UI flags that, when changing, can cause the layout * of the screen to change. Loading Loading @@ -3534,6 +3570,224 @@ public class PhoneWindowManager implements WindowManagerPolicy { setHdmiPlugged(!mHdmiPlugged); } /** {@inheritDoc} */ public void notifyJackSwitchChanged(long whenNanos, int switchCode, boolean switchState) { Slog.d(TAG,"notifyJackSwitchChanged(): switchCode "+switchCode+" switchState "+switchState); synchronized(mHeadsetLock) { if(switchCode == SW_ANC_INSERT) { if(switchState) { mIsAncOn = true; if((mHeadsetJackState & BIT_HEADSET) != 0) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET; } if((mHeadsetJackState & BIT_HEADSET_SPEAKER_ONLY) != 0) { mHeadsetJackState &= ~BIT_HEADSET_SPEAKER_ONLY; mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } if((mHeadsetJackState & BIT_HEADSET_MIC_ONLY) != 0) { mHeadsetJackState &= ~BIT_HEADSET_MIC_ONLY; mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } } else { mIsAncOn = false; if((mHeadsetJackState & BIT_ANC_HEADSET) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_HEADSET; } if((mHeadsetJackState & BIT_ANC_HEADSET_SPEAKER_ONLY) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET_SPEAKER_ONLY; mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } if((mHeadsetJackState & BIT_ANC_HEADSET_MIC_ONLY) != 0) { mHeadsetJackState &= ~BIT_ANC_HEADSET_MIC_ONLY; mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } } } else if ( switchCode == SW_HEADPHONE_INSERT) { if (switchState) { if(mIsAncOn) { mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } else { mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } } else if( (mHeadsetJackState & BIT_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } else if( (mHeadsetJackState & BIT_ANC_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } else { if(mIsAncOn) { mHeadsetJackState &= ~BIT_ANC_HEADSET_SPEAKER_ONLY; } else { mHeadsetJackState &= ~BIT_HEADSET_SPEAKER_ONLY; } } } else if ( switchCode == SW_MICROPHONE_INSERT) { if (switchState) { if(mIsAncOn) { mHeadsetJackState |= BIT_ANC_HEADSET_MIC_ONLY; } else { mHeadsetJackState |= BIT_HEADSET_MIC_ONLY; } } else if( (mHeadsetJackState & BIT_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_HEADSET; mHeadsetJackState |= BIT_HEADSET_SPEAKER_ONLY; } else if( (mHeadsetJackState & BIT_ANC_HEADSET) != 0 ) { mHeadsetJackState &= ~BIT_ANC_HEADSET; mHeadsetJackState |= BIT_ANC_HEADSET_SPEAKER_ONLY; } else { if(mIsAncOn) { mHeadsetJackState &= ~BIT_ANC_HEADSET_MIC_ONLY; } else { mHeadsetJackState &= ~BIT_HEADSET_MIC_ONLY; } } } if( mHeadsetJackState == SW_HEADSET_INSERT ) { // If both Speaker and Mic bits are set, remove them and // set Headset bit to indicate Headset insertion mHeadsetJackState = BIT_HEADSET; } if( mHeadsetJackState == SW_ANC_HEADSET_INSERT ) { mHeadsetJackState = BIT_ANC_HEADSET; } update(); } // synchronized(mHeadsetLock) } private synchronized final void update() { // Retain only relevant bits int headsetState = mHeadsetJackState & SUPPORTED_HEADSETS; // Set default delay to 10msec to allow all the events to reach before sending intent int delay = 10; // reject all suspect transitions: only accept state changes from: // - a: 0 heaset to 1 headset // - b: 1 headset to 0 headset if (mCurHeadsetState == headsetState) { return; } if (headsetState == 0) { Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY); mContext.sendBroadcast(intent); // It can take hundreds of ms flush the audio pipeline after // apps pause audio playback, but audio route changes are // immediate, so delay the route change by 1000ms. // This could be improved once the audio sub-system provides an // interface to clear the audio pipeline. delay = 1000; } else { // Insert the same delay for headset connection so that the connection event is not // broadcast before the disconnection event in case of fast removal/insertion if ( mIntentHandler.hasMessages(0)) { delay = 1000; } } mBroadcastWakeLock.acquire(); Slog.d(TAG,"update(): sending Message to IntentHander with delay of "+delay); mIntentHandler.sendMessageDelayed( mIntentHandler.obtainMessage(0, mHeadsetName), delay); } private synchronized final void sendIntents(String headsetName) { Slog.d(TAG,"sendIntents(): mHeadsetJackState "+mHeadsetJackState+" mCurHeadsetState "+mCurHeadsetState+" mPrevHeadsetState "+mPrevHeadsetState); int headsetState; synchronized(mHeadsetLock) { headsetState = mHeadsetJackState & SUPPORTED_HEADSETS; if (mCurHeadsetState == headsetState) { return; } mPrevHeadsetState = mCurHeadsetState; mCurHeadsetState = headsetState; } int allHeadsets = SUPPORTED_HEADSETS; //Handle unplug events first and then handle plug-in events for (int curHeadset = 1; curHeadset < SUPPORTED_HEADSETS; curHeadset <<= 1) { if (((headsetState & curHeadset) == 0) && ((mPrevHeadsetState & curHeadset) == curHeadset)) { if ((curHeadset & allHeadsets) != 0) { sendIntent(curHeadset, headsetState, mPrevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } for (int curHeadset = 1; curHeadset < SUPPORTED_HEADSETS; curHeadset <<= 1) { if (((headsetState & curHeadset) == curHeadset) && ((mPrevHeadsetState & curHeadset) == 0)) { if ((curHeadset & allHeadsets) != 0) { sendIntent(curHeadset, headsetState, mPrevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } } private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { // Pack up the values and broadcast them to everyone int state = 0; int device = 0; if ((headset & BIT_HEADSET) != 0) { device = AudioManager.DEVICE_OUT_WIRED_HEADSET; } else if ((headset & BIT_HEADSET_SPEAKER_ONLY) != 0) { device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE; } else if ((headset & BIT_HEADSET_MIC_ONLY ) != 0) { device = 0; } else if ((headset & BIT_ANC_HEADSET) != 0) { device = 0;//AudioManager.DEVICE_OUT_ANC_HEADSET; } else if ((headset & BIT_ANC_HEADSET_SPEAKER_ONLY) != 0) { device = 0;//AudioManager.DEVICE_OUT_ANC_HEADPHONE; } else if ((headset & BIT_ANC_HEADSET_MIC_ONLY) != 0) { device = 0; } else { Slog.e(TAG, "setDeviceState() invalid headset type: "+headset); return; } if ((headsetState & headset) != 0) { state = 1; } else { state = 0; } if (mSystemBooted) { final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); if (am == null) { Log.e(TAG, "sendIntent: couldn't get AudioManager reference"); return; } am.setWiredDeviceConnectionState(device, state, headsetName); } else { Slog.d(TAG,"system not booted yet, call setWiredDeviceConnectionState later"); } } } private final Handler mIntentHandler = new Handler() { @Override public void handleMessage(Message msg) { Slog.d(TAG,"Headset detect: Inside handleMessage() for IntentHandler" + (String)msg.obj); if (mSystemBooted) { sendIntents((String)msg.obj); mBroadcastWakeLock.release(); } else { Log.e(TAG, "system not booted yet, send headset intent later"); mHeadsetIntent = true; mHeadsetName = (String)msg.obj; } } }; /** * @return Whether music is being played right now. */ Loading Loading @@ -4471,6 +4725,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void systemBooted() { synchronized (mLock) { mSystemBooted = true; if (mHeadsetIntent) { Log.e(TAG, "send headset intent after system booted"); sendIntents(mHeadsetName); mBroadcastWakeLock.release(); } } } Loading
services/input/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ ifeq ($(BOARD_USE_LEGACY_TRACKPAD),true) LOCAL_CFLAGS += -DLEGACY_TRACKPAD endif ifeq ($(BOARD_USES_ALSA_AUDIO),true) LOCAL_CFLAGS += -DALSA_HEADSET_DETECTION endif LOCAL_MODULE:= libinput LOCAL_MODULE_TAGS := optional Loading
services/input/EventHub.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ EventHub::EventHub(void) : mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mNeedToSendHeadPhoneEvent(false), mNeedToSendMicroPhoneEvent(false), mHeadsetDeviceId(-1), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); Loading Loading @@ -693,6 +694,22 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz event->type = DEVICE_ADDED; event += 1; mNeedToSendFinishedDeviceScan = true; #ifdef ALSA_HEADSET_DETECTION if(device->classes == INPUT_DEVICE_CLASS_SWITCH) { mLock.unlock(); int state = getSwitchState(device->id, SW_HEADPHONE_INSERT); if(state > 0) { mNeedToSendHeadPhoneEvent = true; } state = getSwitchState(device->id, SW_MICROPHONE_INSERT); mLock.lock(); if(state > 0) { mNeedToSendMicroPhoneEvent = true; } mHeadsetDeviceId = device->id; } #endif if (--capacity == 0) { break; } Loading @@ -708,6 +725,33 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz } } #ifdef ALSA_HEADSET_DETECTION if(mNeedToSendHeadPhoneEvent) { event->type = EV_SW; event->code = SW_HEADPHONE_INSERT; event->value = 1; event->deviceId = mHeadsetDeviceId; event->when = systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendHeadPhoneEvent = false; event += 1; if (--capacity == 0) { break; } } if(mNeedToSendMicroPhoneEvent) { event->type = EV_SW; event->code = SW_MICROPHONE_INSERT; event->value = 1; event->deviceId = mHeadsetDeviceId; event->when = systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendMicroPhoneEvent = false; event += 1; if (--capacity == 0) { break; } } #endif // Grab the next input event. bool deviceChanged = false; while (mPendingEventIndex < mPendingEventCount) { Loading Loading @@ -1039,6 +1083,8 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { // See if this is a keyboard. Ignore everything in the button range except for // joystick and gamepad buttons which are handled like keyboards for the most part. bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), sizeof_bit_array(BTN_9)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK), sizeof_bit_array(KEY_MAX + 1)); bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), Loading
services/input/EventHub.h +3 −0 Original line number Diff line number Diff line Loading @@ -389,6 +389,9 @@ private: bool mNeedToSendFinishedDeviceScan; bool mNeedToReopenDevices; bool mNeedToScanDevices; bool mNeedToSendHeadPhoneEvent; bool mNeedToSendMicroPhoneEvent; int mHeadsetDeviceId; Vector<String8> mExcludedDevices; int mEpollFd; Loading