Loading services/core/java/com/android/server/WiredAccessoryManager.java +259 −22 Original line number Diff line number Diff line Loading @@ -70,6 +70,12 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private static final String NAME_H2W = "h2w"; private static final String NAME_USB_AUDIO = "usb_audio"; private static final String NAME_HDMI_AUDIO = "hdmi_audio"; private static final String NAME_DP_AUDIO = "soc:qcom,msm-ext-disp"; // within a device, a single stream supports DP private static final String[] DP_AUDIO_CONNS = { NAME_DP_AUDIO + "/1/0", NAME_DP_AUDIO + "/0/0" }; private static final String NAME_HDMI = "hdmi"; private static final int MSG_NEW_DEVICE_STATE = 1; Loading @@ -81,6 +87,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final AudioManager mAudioManager; private int mHeadsetState; private int mDpCount; private int mSwitchValues; Loading Loading @@ -123,7 +130,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (ExtconUEventObserver.extconExists()) { if (ExtconUEventObserver.extconExists() && mExtconObserver.uEventCount() > 0) { if (mUseDevInputEventForAudioJack) { Log.w(TAG, "Both input event and extcon are used for audio jack," + " please just choose one."); Loading Loading @@ -172,7 +179,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { break; } updateLocked(NAME_H2W, updateLocked(NAME_H2W, "", (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset); } } Loading @@ -193,25 +200,32 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { * results in support for the last one plugged in. Similarly, unplugging either is seen as * unplugging all. * * For Display port allow up to two connections. * Block display port request if HDMI already connected and vice versa. * * @param newName One of the NAME_xxx variables defined above. * @param newState 0 or one of the BIT_xxx variables defined above. */ private void updateLocked(String newName, int newState) { private void updateLocked(String newName, String address, int newState) { // Retain only relevant bits int headsetState = newState & SUPPORTED_HEADSETS; int newDpState = newState & BIT_HDMI_AUDIO; int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG; int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL; int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT); boolean h2wStateChange = true; boolean usbStateChange = true; boolean dpBitState = (mHeadsetState & BIT_HDMI_AUDIO) > 0; boolean dpCountState = mDpCount != 0; if (LOG) { Slog.v(TAG, "newName=" + newName + " newState=" + newState + " headsetState=" + headsetState + " prev headsetState=" + mHeadsetState); + " prev headsetState=" + mHeadsetState + " num of active dp conns= " + mDpCount); } if (mHeadsetState == headsetState) { if (mHeadsetState == headsetState && !newName.startsWith(NAME_DP_AUDIO)) { Log.e(TAG, "No state change."); return; } Loading @@ -234,11 +248,42 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { return; } if (newName.startsWith(NAME_DP_AUDIO)) { if ((newDpState > 0) && (mDpCount < DP_AUDIO_CONNS.length) && (dpBitState == dpCountState)) { // Allow DP0 if no HDMI previously connected. // Allow second request only if DP connected previously. mDpCount++; } else if ((newDpState == 0) && (mDpCount > 0)) { mDpCount--; } else { Log.e(TAG, "No state change for DP."); return; } } mWakeLock.acquire(); Log.i(TAG, "MSG_NEW_DEVICE_STATE"); Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, mHeadsetState, ""); // Send a combined name, address string separated by | Message msg; if (newName.startsWith(NAME_DP_AUDIO)) { int pseudoHeadsetState = mHeadsetState; if (dpBitState && (newDpState != 0)) { // One DP already connected, so allow request to connect second. pseudoHeadsetState = mHeadsetState & (~BIT_HDMI_AUDIO); } msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, pseudoHeadsetState, NAME_DP_AUDIO + "/" + address); if ((headsetState == 0) && (mDpCount != 0)) { // Atleast one DP is connected, so keep mHeadsetState's DP bit set. headsetState = headsetState | BIT_HDMI_AUDIO; } } else { msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, mHeadsetState, newName + "/" + address); } mHandler.sendMessage(msg); mHeadsetState = headsetState; Loading @@ -261,12 +306,13 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { }; private void setDevicesState( int headsetState, int prevHeadsetState, String headsetName) { int headsetState, int prevHeadsetState, String headsetNameAddr) { synchronized (mLock) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetNameAddr); allHeadsets &= ~curHeadset; } } Loading @@ -274,7 +320,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } private void setDeviceStateLocked(int headset, int headsetState, int prevHeadsetState, String headsetName) { int headsetState, int prevHeadsetState, String headsetNameAddr) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int outDevice = 0; int inDevice = 0; Loading Loading @@ -305,15 +351,18 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (LOG) { Slog.v(TAG, "headsetName: " + headsetName + Slog.v(TAG, "headsetNameAddr: " + headsetNameAddr + (state == 1 ? " connected" : " disconnected")); } String[] hs = headsetNameAddr.split("/"); if (outDevice != 0) { mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName); mAudioManager.setWiredDeviceConnectionState(outDevice, state, (hs.length > 1 ? hs[1] : ""), hs[0]); } if (inDevice != 0) { mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName); mAudioManager.setWiredDeviceConnectionState(inDevice, state, (hs.length > 1 ? hs[1] : ""), hs[0]); } } } Loading Loading @@ -416,22 +465,91 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } } for (String conn : DP_AUDIO_CONNS) { // Monitor DisplayPort if (LOG) { Slog.v(TAG, "Monitor DP conn " + conn); } uei = new UEventInfo(conn, BIT_HDMI_AUDIO, 0, 0); if (uei.checkSwitchExists()) { retVal.add(uei); } else { Slog.w(TAG, "Conn " + conn + " does not have DP audio support"); } } return retVal; } @Override public void onUEvent(UEventObserver.UEvent event) { if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); String devPath = event.get("DEVPATH"); String name = event.get("NAME"); int state = 0; if (name == null) { name = event.get("SWITCH_NAME"); } try { String devPath = event.get("DEVPATH"); String name = event.get("SWITCH_NAME"); int state = Integer.parseInt(event.get("SWITCH_STATE")); synchronized (mLock) { updateStateLocked(devPath, name, state); if (name.startsWith(NAME_DP_AUDIO)) { String stateStr = event.get("STATE"); int offset = 0; int length = stateStr.length(); // parse DP=1\nHDMI=1\0 while (offset < length) { int equals = stateStr.indexOf('=', offset); if (equals > offset) { String intfName = stateStr.substring(offset, equals); if (intfName.equals("DP")) { state = Integer.parseInt( stateStr.substring(equals + 1, equals + 2)); break; } } offset = equals + 3; } } else { state = Integer.parseInt(event.get("SWITCH_STATE")); } } catch (NumberFormatException e) { Slog.e(TAG, "Could not parse switch state from event " + event); Slog.i(TAG, "couldn't get state from event, checking node"); for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); if (name.equals(uei.getDevName())) { char[] buffer = new char[1024]; int len = 0; try { FileReader file = new FileReader(uei.getSwitchStatePath()); len = file.read(buffer, 0, 1024); file.close(); } catch (FileNotFoundException e1) { Slog.e(TAG, "file not found"); break; } catch (Exception e11) { Slog.e(TAG, "onUEvent exception", e11); } try { state = Integer.parseInt((new String(buffer, 0, len)).trim()); } catch (NumberFormatException e2) { Slog.e(TAG, "could not convert to number"); break; } break; } } } synchronized (mLock) { updateStateLocked(devPath, name, state); } } Loading @@ -439,7 +557,8 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); if (devPath.equals(uei.getDevPath())) { updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state)); updateLocked(name, uei.getDevAddress(), uei.computeNewHeadsetState(mHeadsetState, state)); return; } } Loading @@ -447,26 +566,140 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final class UEventInfo { private final String mDevName; private String mDevAddress; private final int mState1Bits; private final int mState2Bits; private final int mStateNbits; private int mDevIndex; private int mCableIndex; public UEventInfo(String devName, int state1Bits, int state2Bits, int stateNbits) { mDevName = devName; mDevAddress = "controller=0;stream=0"; mState1Bits = state1Bits; mState2Bits = state2Bits; mStateNbits = stateNbits; mDevIndex = -1; mCableIndex = -1; if (mDevName.startsWith(NAME_DP_AUDIO)) { int idx = mDevName.indexOf("/"); if (idx != -1) { int idx2 = mDevName.indexOf("/", idx + 1); assert(idx2 != -1); int dev = Integer.parseInt(mDevName.substring(idx + 1, idx2)); int cable = Integer.parseInt(mDevName.substring(idx2 + 1)); mDevAddress = "controller=" + cable + ";stream=" + dev; if (LOG) { Slog.v(TAG, "UEvent dev address " + mDevAddress); } checkDevIndex(dev); checkCableIndex(cable); } } } private void checkDevIndex(int devIndex) { int index = 0; char[] buffer = new char[1024]; while (true) { String devPath = String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/name", NAME_DP_AUDIO, index); if (LOG) { Slog.v(TAG, "checkDevIndex " + devPath); } File f = new File(devPath); if (!f.exists()) { Slog.e(TAG, "file " + devPath + " not found"); break; } try { FileReader file = new FileReader(f); int len = file.read(buffer, 0, 1024); file.close(); String devName = (new String(buffer, 0, len)).trim(); if (devName.startsWith(NAME_DP_AUDIO) && index == devIndex) { mDevIndex = devIndex; break; } else { index++; } } catch (Exception e) { Slog.e(TAG, "checkDevIndex exception", e); break; } } } private void checkCableIndex(int cableIndex) { if (mDevIndex == -1) { return; } int index = 0; char[] buffer = new char[1024]; while (true) { String cablePath = String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/name", NAME_DP_AUDIO, mDevIndex, index); if (LOG) { Slog.v(TAG, "checkCableIndex " + cablePath); } File f = new File(cablePath); if (!f.exists()) { Slog.e(TAG, "file " + cablePath + " not found"); break; } try { FileReader file = new FileReader(f); int len = file.read(buffer, 0, 1024); file.close(); String cableName = (new String(buffer, 0, len)).trim(); if (cableName.equals("DP") && index == cableIndex) { mCableIndex = cableIndex; break; } else { index++; } } catch (Exception e) { Slog.e(TAG, "checkCableIndex exception", e); break; } } } public String getDevName() { return mDevName; } public String getDevAddress() { return mDevAddress; } public String getDevPath() { if (mDevName.startsWith(NAME_DP_AUDIO)) { return String.format(Locale.US, "/devices/platform/soc/%s/extcon/extcon%d", NAME_DP_AUDIO, mDevIndex); } return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName); } public String getSwitchStatePath() { if (mDevName.startsWith(NAME_DP_AUDIO)) { return String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/state", NAME_DP_AUDIO, mDevIndex, mCableIndex); } return String.format(Locale.US, "/sys/class/switch/%s/state", mDevName); } Loading Loading @@ -518,6 +751,10 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } public int uEventCount() { return mExtconInfos.size(); } @Override public Pair<Integer, Integer> parseState(ExtconInfo extconInfo, String status) { if (LOG) Slog.v(TAG, "status " + status); Loading @@ -538,7 +775,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { synchronized (mLock) { int mask = maskAndState.first; int state = maskAndState.second; updateLocked(name, mHeadsetState & ~(mask & ~state) | (mask & state)); updateLocked(name, "", mHeadsetState & ~(mask & ~state) | (mask & state)); return; } } Loading Loading
services/core/java/com/android/server/WiredAccessoryManager.java +259 −22 Original line number Diff line number Diff line Loading @@ -70,6 +70,12 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private static final String NAME_H2W = "h2w"; private static final String NAME_USB_AUDIO = "usb_audio"; private static final String NAME_HDMI_AUDIO = "hdmi_audio"; private static final String NAME_DP_AUDIO = "soc:qcom,msm-ext-disp"; // within a device, a single stream supports DP private static final String[] DP_AUDIO_CONNS = { NAME_DP_AUDIO + "/1/0", NAME_DP_AUDIO + "/0/0" }; private static final String NAME_HDMI = "hdmi"; private static final int MSG_NEW_DEVICE_STATE = 1; Loading @@ -81,6 +87,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final AudioManager mAudioManager; private int mHeadsetState; private int mDpCount; private int mSwitchValues; Loading Loading @@ -123,7 +130,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (ExtconUEventObserver.extconExists()) { if (ExtconUEventObserver.extconExists() && mExtconObserver.uEventCount() > 0) { if (mUseDevInputEventForAudioJack) { Log.w(TAG, "Both input event and extcon are used for audio jack," + " please just choose one."); Loading Loading @@ -172,7 +179,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { break; } updateLocked(NAME_H2W, updateLocked(NAME_H2W, "", (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset); } } Loading @@ -193,25 +200,32 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { * results in support for the last one plugged in. Similarly, unplugging either is seen as * unplugging all. * * For Display port allow up to two connections. * Block display port request if HDMI already connected and vice versa. * * @param newName One of the NAME_xxx variables defined above. * @param newState 0 or one of the BIT_xxx variables defined above. */ private void updateLocked(String newName, int newState) { private void updateLocked(String newName, String address, int newState) { // Retain only relevant bits int headsetState = newState & SUPPORTED_HEADSETS; int newDpState = newState & BIT_HDMI_AUDIO; int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG; int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL; int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT); boolean h2wStateChange = true; boolean usbStateChange = true; boolean dpBitState = (mHeadsetState & BIT_HDMI_AUDIO) > 0; boolean dpCountState = mDpCount != 0; if (LOG) { Slog.v(TAG, "newName=" + newName + " newState=" + newState + " headsetState=" + headsetState + " prev headsetState=" + mHeadsetState); + " prev headsetState=" + mHeadsetState + " num of active dp conns= " + mDpCount); } if (mHeadsetState == headsetState) { if (mHeadsetState == headsetState && !newName.startsWith(NAME_DP_AUDIO)) { Log.e(TAG, "No state change."); return; } Loading @@ -234,11 +248,42 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { return; } if (newName.startsWith(NAME_DP_AUDIO)) { if ((newDpState > 0) && (mDpCount < DP_AUDIO_CONNS.length) && (dpBitState == dpCountState)) { // Allow DP0 if no HDMI previously connected. // Allow second request only if DP connected previously. mDpCount++; } else if ((newDpState == 0) && (mDpCount > 0)) { mDpCount--; } else { Log.e(TAG, "No state change for DP."); return; } } mWakeLock.acquire(); Log.i(TAG, "MSG_NEW_DEVICE_STATE"); Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, mHeadsetState, ""); // Send a combined name, address string separated by | Message msg; if (newName.startsWith(NAME_DP_AUDIO)) { int pseudoHeadsetState = mHeadsetState; if (dpBitState && (newDpState != 0)) { // One DP already connected, so allow request to connect second. pseudoHeadsetState = mHeadsetState & (~BIT_HDMI_AUDIO); } msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, pseudoHeadsetState, NAME_DP_AUDIO + "/" + address); if ((headsetState == 0) && (mDpCount != 0)) { // Atleast one DP is connected, so keep mHeadsetState's DP bit set. headsetState = headsetState | BIT_HDMI_AUDIO; } } else { msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, mHeadsetState, newName + "/" + address); } mHandler.sendMessage(msg); mHeadsetState = headsetState; Loading @@ -261,12 +306,13 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { }; private void setDevicesState( int headsetState, int prevHeadsetState, String headsetName) { int headsetState, int prevHeadsetState, String headsetNameAddr) { synchronized (mLock) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetNameAddr); allHeadsets &= ~curHeadset; } } Loading @@ -274,7 +320,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } private void setDeviceStateLocked(int headset, int headsetState, int prevHeadsetState, String headsetName) { int headsetState, int prevHeadsetState, String headsetNameAddr) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int outDevice = 0; int inDevice = 0; Loading Loading @@ -305,15 +351,18 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (LOG) { Slog.v(TAG, "headsetName: " + headsetName + Slog.v(TAG, "headsetNameAddr: " + headsetNameAddr + (state == 1 ? " connected" : " disconnected")); } String[] hs = headsetNameAddr.split("/"); if (outDevice != 0) { mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName); mAudioManager.setWiredDeviceConnectionState(outDevice, state, (hs.length > 1 ? hs[1] : ""), hs[0]); } if (inDevice != 0) { mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName); mAudioManager.setWiredDeviceConnectionState(inDevice, state, (hs.length > 1 ? hs[1] : ""), hs[0]); } } } Loading Loading @@ -416,22 +465,91 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } } for (String conn : DP_AUDIO_CONNS) { // Monitor DisplayPort if (LOG) { Slog.v(TAG, "Monitor DP conn " + conn); } uei = new UEventInfo(conn, BIT_HDMI_AUDIO, 0, 0); if (uei.checkSwitchExists()) { retVal.add(uei); } else { Slog.w(TAG, "Conn " + conn + " does not have DP audio support"); } } return retVal; } @Override public void onUEvent(UEventObserver.UEvent event) { if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); String devPath = event.get("DEVPATH"); String name = event.get("NAME"); int state = 0; if (name == null) { name = event.get("SWITCH_NAME"); } try { String devPath = event.get("DEVPATH"); String name = event.get("SWITCH_NAME"); int state = Integer.parseInt(event.get("SWITCH_STATE")); synchronized (mLock) { updateStateLocked(devPath, name, state); if (name.startsWith(NAME_DP_AUDIO)) { String stateStr = event.get("STATE"); int offset = 0; int length = stateStr.length(); // parse DP=1\nHDMI=1\0 while (offset < length) { int equals = stateStr.indexOf('=', offset); if (equals > offset) { String intfName = stateStr.substring(offset, equals); if (intfName.equals("DP")) { state = Integer.parseInt( stateStr.substring(equals + 1, equals + 2)); break; } } offset = equals + 3; } } else { state = Integer.parseInt(event.get("SWITCH_STATE")); } } catch (NumberFormatException e) { Slog.e(TAG, "Could not parse switch state from event " + event); Slog.i(TAG, "couldn't get state from event, checking node"); for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); if (name.equals(uei.getDevName())) { char[] buffer = new char[1024]; int len = 0; try { FileReader file = new FileReader(uei.getSwitchStatePath()); len = file.read(buffer, 0, 1024); file.close(); } catch (FileNotFoundException e1) { Slog.e(TAG, "file not found"); break; } catch (Exception e11) { Slog.e(TAG, "onUEvent exception", e11); } try { state = Integer.parseInt((new String(buffer, 0, len)).trim()); } catch (NumberFormatException e2) { Slog.e(TAG, "could not convert to number"); break; } break; } } } synchronized (mLock) { updateStateLocked(devPath, name, state); } } Loading @@ -439,7 +557,8 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); if (devPath.equals(uei.getDevPath())) { updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state)); updateLocked(name, uei.getDevAddress(), uei.computeNewHeadsetState(mHeadsetState, state)); return; } } Loading @@ -447,26 +566,140 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final class UEventInfo { private final String mDevName; private String mDevAddress; private final int mState1Bits; private final int mState2Bits; private final int mStateNbits; private int mDevIndex; private int mCableIndex; public UEventInfo(String devName, int state1Bits, int state2Bits, int stateNbits) { mDevName = devName; mDevAddress = "controller=0;stream=0"; mState1Bits = state1Bits; mState2Bits = state2Bits; mStateNbits = stateNbits; mDevIndex = -1; mCableIndex = -1; if (mDevName.startsWith(NAME_DP_AUDIO)) { int idx = mDevName.indexOf("/"); if (idx != -1) { int idx2 = mDevName.indexOf("/", idx + 1); assert(idx2 != -1); int dev = Integer.parseInt(mDevName.substring(idx + 1, idx2)); int cable = Integer.parseInt(mDevName.substring(idx2 + 1)); mDevAddress = "controller=" + cable + ";stream=" + dev; if (LOG) { Slog.v(TAG, "UEvent dev address " + mDevAddress); } checkDevIndex(dev); checkCableIndex(cable); } } } private void checkDevIndex(int devIndex) { int index = 0; char[] buffer = new char[1024]; while (true) { String devPath = String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/name", NAME_DP_AUDIO, index); if (LOG) { Slog.v(TAG, "checkDevIndex " + devPath); } File f = new File(devPath); if (!f.exists()) { Slog.e(TAG, "file " + devPath + " not found"); break; } try { FileReader file = new FileReader(f); int len = file.read(buffer, 0, 1024); file.close(); String devName = (new String(buffer, 0, len)).trim(); if (devName.startsWith(NAME_DP_AUDIO) && index == devIndex) { mDevIndex = devIndex; break; } else { index++; } } catch (Exception e) { Slog.e(TAG, "checkDevIndex exception", e); break; } } } private void checkCableIndex(int cableIndex) { if (mDevIndex == -1) { return; } int index = 0; char[] buffer = new char[1024]; while (true) { String cablePath = String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/name", NAME_DP_AUDIO, mDevIndex, index); if (LOG) { Slog.v(TAG, "checkCableIndex " + cablePath); } File f = new File(cablePath); if (!f.exists()) { Slog.e(TAG, "file " + cablePath + " not found"); break; } try { FileReader file = new FileReader(f); int len = file.read(buffer, 0, 1024); file.close(); String cableName = (new String(buffer, 0, len)).trim(); if (cableName.equals("DP") && index == cableIndex) { mCableIndex = cableIndex; break; } else { index++; } } catch (Exception e) { Slog.e(TAG, "checkCableIndex exception", e); break; } } } public String getDevName() { return mDevName; } public String getDevAddress() { return mDevAddress; } public String getDevPath() { if (mDevName.startsWith(NAME_DP_AUDIO)) { return String.format(Locale.US, "/devices/platform/soc/%s/extcon/extcon%d", NAME_DP_AUDIO, mDevIndex); } return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName); } public String getSwitchStatePath() { if (mDevName.startsWith(NAME_DP_AUDIO)) { return String.format(Locale.US, "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/state", NAME_DP_AUDIO, mDevIndex, mCableIndex); } return String.format(Locale.US, "/sys/class/switch/%s/state", mDevName); } Loading Loading @@ -518,6 +751,10 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } public int uEventCount() { return mExtconInfos.size(); } @Override public Pair<Integer, Integer> parseState(ExtconInfo extconInfo, String status) { if (LOG) Slog.v(TAG, "status " + status); Loading @@ -538,7 +775,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { synchronized (mLock) { int mask = maskAndState.first; int state = maskAndState.second; updateLocked(name, mHeadsetState & ~(mask & ~state) | (mask & state)); updateLocked(name, "", mHeadsetState & ~(mask & ~state) | (mask & state)); return; } } Loading