Use extcon to listen for hdmi state changes

Test: flash; watch "adb shell dumpsys activity broadcasts | grep  HDMI"
Bug: 116011465
Change-Id: Iba8d71450476a0729a19aec4261cfc6ff6c75e05
diff --git a/services/core/java/com/android/server/ExtconStateObserver.java b/services/core/java/com/android/server/ExtconStateObserver.java
index 6b561c7..92f30ff 100644
--- a/services/core/java/com/android/server/ExtconStateObserver.java
+++ b/services/core/java/com/android/server/ExtconStateObserver.java
@@ -21,7 +21,6 @@
 import android.util.Slog;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 
 /**
@@ -36,31 +35,18 @@
     private static final boolean LOG = false;
 
     /**
-     * Parses the current state from the state file for {@code extconInfo} and calls {@link
-     * #updateState(ExtconInfo, String, Object)}
+     * Parses the current state from the state file for {@code extconInfo}.
      *
-     * @param extconInfo the extconInfo to update state for
+     * @param extconInfo the extconInfo to parse state for
      * @see #parseState(ExtconInfo, String)
      * @see ExtconInfo#getStatePath()
      */
-    public void updateStateFromFile(ExtconInfo extconInfo) {
+    @Nullable
+    public S parseStateFromFile(ExtconInfo extconInfo) throws IOException {
         String statePath = extconInfo.getStatePath();
-        try {
-            S state =
-                    parseState(
-                            extconInfo,
-                            FileUtils.readTextFile(new File(statePath), 0, null).trim());
-            if (state != null) {
-                updateState(extconInfo, extconInfo.getName(), state);
-            }
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, statePath + " not found while attempting to determine initial state", e);
-        } catch (IOException e) {
-            Slog.e(
-                    TAG,
-                    "Error reading " + statePath + " while attempting to determine initial state ",
-                    e);
-        }
+        return parseState(
+                extconInfo,
+                FileUtils.readTextFile(new File(statePath), 0, null).trim());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 282746a..59c6d0a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -275,6 +275,8 @@
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.widget.PointerLocationView;
+import com.android.server.ExtconStateObserver;
+import com.android.server.ExtconUEventObserver;
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
 import com.android.server.SystemServiceManager;
@@ -296,6 +298,7 @@
 import com.android.server.wm.utils.InsetUtils;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -5707,7 +5710,7 @@
                 char[] buf = new char[15];
                 int n = reader.read(buf);
                 if (n > 1) {
-                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
+                    plugged = 0 != Integer.parseInt(new String(buf, 0, n - 1));
                 }
             } catch (IOException ex) {
                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
@@ -5721,6 +5724,10 @@
                     }
                 }
             }
+        } else if (ExtconUEventObserver.extconExists()) {
+            HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();
+            plugged = observer.init();
+            mHDMIObserver = observer;
         }
         // This dance forces the code in setHdmiPlugged to run.
         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
@@ -8315,4 +8322,40 @@
         }
         return false;
     }
+
+    private class HdmiVideoExtconUEventObserver extends ExtconStateObserver<Boolean> {
+        private static final String HDMI_EXIST = "HDMI=1";
+        private final ExtconInfo mHdmi = new ExtconInfo("hdmi");
+
+        private boolean init() {
+            boolean plugged = false;
+            try {
+                plugged = parseStateFromFile(mHdmi);
+            } catch (FileNotFoundException e) {
+                Slog.w(TAG, mHdmi.getStatePath()
+                        + " not found while attempting to determine initial state", e);
+            } catch (IOException e) {
+                Slog.e(
+                        TAG,
+                        "Error reading " + mHdmi.getStatePath()
+                                + " while attempting to determine initial state",
+                        e);
+            }
+            startObserving(mHdmi);
+            return plugged;
+        }
+
+        @Override
+        public void updateState(ExtconInfo extconInfo, String eventName, Boolean state) {
+            mDefaultDisplayPolicy.setHdmiPlugged(state);
+        }
+
+        @Override
+        public Boolean parseState(ExtconInfo extconIfno, String state) {
+            // extcon event state changes from kernel4.9
+            // new state will be like STATE=HDMI=1
+            return state.contains(HDMI_EXIST);
+        }
+    }
+
 }