107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant/*
207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * Copyright (C) 2018 The Android Open Source Project
307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant *
407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * Licensed under the Apache License, Version 2.0 (the "License");
507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * you may not use this file except in compliance with the License.
607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * You may obtain a copy of the License at
707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant *
807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant *      http://www.apache.org/licenses/LICENSE-2.0
907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant *
1007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * Unless required by applicable law or agreed to in writing, software
1107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * distributed under the License is distributed on an "AS IS" BASIS,
1207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * See the License for the specific language governing permissions and
1407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * limitations under the License.
1507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant */
1607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
1707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chantpackage com.android.server.usb;
1807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
1907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant/**
2007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant * Detects and reports ALSA jack state and events.
2107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant */
2207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chantpublic final class UsbAlsaJackDetector implements Runnable {
2307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private static final String TAG = "UsbAlsaJackDetector";
2407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
2507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private static native boolean nativeHasJackDetect(int card);
2607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private native boolean nativeJackDetect(int card);
2707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private native boolean nativeOutputJackConnected(int card);
2807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private native boolean nativeInputJackConnected(int card);
2907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
3007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private boolean mStopJackDetect = false;
3107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private UsbAlsaDevice mAlsaDevice;
3207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
3307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    /* use startJackDetect to create a UsbAlsaJackDetector */
3407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    private UsbAlsaJackDetector(UsbAlsaDevice device) {
3507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        mAlsaDevice = device;
3607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
3707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
3807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    /** If jack detection is detected on the given Alsa Device,
3907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * create and return a UsbAlsaJackDetector which will update wired device state
4007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * each time a jack detection event is registered.
4107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     *
4207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * @returns UsbAlsaJackDetector if jack detect is supported, or null.
4307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     */
4407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public static UsbAlsaJackDetector startJackDetect(UsbAlsaDevice device) {
4507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        if (!nativeHasJackDetect(device.getCardNum())) {
4607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant            return null;
4707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        }
4807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        UsbAlsaJackDetector jackDetector = new UsbAlsaJackDetector(device);
4907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
5007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        // This thread will exit once the USB device disappears.
5107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        // It can also be convinced to stop with pleaseStop().
5207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        new Thread(jackDetector, "USB jack detect thread").start();
5307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        return jackDetector;
5407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
5507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
5607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public boolean isInputJackConnected() {
5707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        return nativeInputJackConnected(mAlsaDevice.getCardNum());
5807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
5907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
6007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public boolean isOutputJackConnected() {
6107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        return nativeOutputJackConnected(mAlsaDevice.getCardNum());
6207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
6307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
6407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    /**
6507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * Stop the jack detect thread from calling back into UsbAlsaDevice.
6607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * This doesn't force the thread to stop (which is deprecated in java and dangerous due to
6707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * locking issues), but will cause the thread to exit at the next safe opportunity.
6807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     */
6907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public void pleaseStop() {
7007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        synchronized (this) {
7107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant            mStopJackDetect = true;
7207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        }
7307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
7407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
7507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    /**
7607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * Called by nativeJackDetect each time a jack detect event is reported.
7707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * @return false when the jackDetect thread should stop.  true otherwise.
7807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     */
7907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public boolean jackDetectCallback() {
8007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        synchronized (this) {
8107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant            if (mStopJackDetect) {
8207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant                return false;
8307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant            }
8407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant            mAlsaDevice.updateWiredDeviceConnectionState(true);
8507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        }
8607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        return true;
8707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
8807a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
8907a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    /**
9007a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * This will call jackDetectCallback each time it detects a jack detect event.
9107a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     * If jackDetectCallback returns false, this function will return.
9207a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant     */
9307a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    public void run() {
9407a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant        nativeJackDetect(mAlsaDevice.getCardNum());
9507a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant    }
9607a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant}
9707a97da51fc7d43db9903d793d614340b1cf3b67Andrew Chant
98