1 /*
2  * Copyright (C) 2018 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.android.server.usb;
18 
19 /**
20  * Detects and reports ALSA jack state and events.
21  */
22 public final class UsbAlsaJackDetector implements Runnable {
23     private static final String TAG = "UsbAlsaJackDetector";
24 
nativeHasJackDetect(int card)25     private static native boolean nativeHasJackDetect(int card);
nativeJackDetect(int card)26     private native boolean nativeJackDetect(int card);
nativeOutputJackConnected(int card)27     private native boolean nativeOutputJackConnected(int card);
nativeInputJackConnected(int card)28     private native boolean nativeInputJackConnected(int card);
29 
30     private boolean mStopJackDetect = false;
31     private UsbAlsaDevice mAlsaDevice;
32 
33     /* use startJackDetect to create a UsbAlsaJackDetector */
UsbAlsaJackDetector(UsbAlsaDevice device)34     private UsbAlsaJackDetector(UsbAlsaDevice device) {
35         mAlsaDevice = device;
36     }
37 
38     /** If jack detection is detected on the given Alsa Device,
39      * create and return a UsbAlsaJackDetector which will update wired device state
40      * each time a jack detection event is registered.
41      *
42      * @returns UsbAlsaJackDetector if jack detect is supported, or null.
43      */
startJackDetect(UsbAlsaDevice device)44     public static UsbAlsaJackDetector startJackDetect(UsbAlsaDevice device) {
45         if (!nativeHasJackDetect(device.getCardNum())) {
46             return null;
47         }
48         UsbAlsaJackDetector jackDetector = new UsbAlsaJackDetector(device);
49 
50         // This thread will exit once the USB device disappears.
51         // It can also be convinced to stop with pleaseStop().
52         new Thread(jackDetector, "USB jack detect thread").start();
53         return jackDetector;
54     }
55 
isInputJackConnected()56     public boolean isInputJackConnected() {
57         return nativeInputJackConnected(mAlsaDevice.getCardNum());
58     }
59 
isOutputJackConnected()60     public boolean isOutputJackConnected() {
61         return nativeOutputJackConnected(mAlsaDevice.getCardNum());
62     }
63 
64     /**
65      * Stop the jack detect thread from calling back into UsbAlsaDevice.
66      * This doesn't force the thread to stop (which is deprecated in java and dangerous due to
67      * locking issues), but will cause the thread to exit at the next safe opportunity.
68      */
pleaseStop()69     public void pleaseStop() {
70         synchronized (this) {
71             mStopJackDetect = true;
72         }
73     }
74 
75     /**
76      * Called by nativeJackDetect each time a jack detect event is reported.
77      * @return false when the jackDetect thread should stop.  true otherwise.
78      */
jackDetectCallback()79     public boolean jackDetectCallback() {
80         synchronized (this) {
81             if (mStopJackDetect) {
82                 return false;
83             }
84             mAlsaDevice.updateWiredDeviceConnectionState(true);
85         }
86         return true;
87     }
88 
89     /**
90      * This will call jackDetectCallback each time it detects a jack detect event.
91      * If jackDetectCallback returns false, this function will return.
92      */
run()93     public void run() {
94         nativeJackDetect(mAlsaDevice.getCardNum());
95     }
96 }
97 
98