Snap for 7486544 from 2d1ee7de713a93d08677e19e93a5a2ced82afaa5 to sc-release

Change-Id: Idd9887512ce164ecd335922809d8c22ebff78a0a
diff --git a/OWNERS b/OWNERS
index 64b0ed4..4d45629 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
 depstein@google.com
 yabinh@google.com
 agathaman@google.com
+hseog@google.com
diff --git a/src/com/android/car/rotary/RotaryService.java b/src/com/android/car/rotary/RotaryService.java
index ae2b425..7f26275 100644
--- a/src/com/android/car/rotary/RotaryService.java
+++ b/src/com/android/car/rotary/RotaryService.java
@@ -17,6 +17,7 @@
 
 import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;
 import static android.car.CarOccupantZoneManager.DisplayTypeEnum;
+import static android.car.settings.CarSettings.Secure.KEY_ROTARY_KEY_EVENT_FILTER;
 import static android.provider.Settings.Secure.DEFAULT_INPUT_METHOD;
 import static android.provider.Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS;
 import static android.provider.Settings.Secure.ENABLED_INPUT_METHODS;
@@ -324,6 +325,9 @@
     /** Observer to update {@link #mTouchInputMethod} when the user switches IMEs. */
     private ContentObserver mInputMethodObserver;
 
+    /** Observer to update service info when the developer toggles key event filtering. */
+    private ContentObserver mKeyEventFilterObserver;
+
     private SharedPreferences mPrefs;
     private UserManager mUserManager;
 
@@ -444,6 +448,11 @@
      */
     @Nullable private Context mWindowContext;
 
+    /**
+     * Mapping from test keycodes to production keycodes. During development, you can use a USB
+     * keyboard as a stand-in for rotary hardware. To enable this: {@code adb shell settings put
+     * secure android.car.ROTARY_KEY_EVENT_FILTER 1}.
+     */
     private static final Map<Integer, Integer> TEST_TO_REAL_KEYCODE_MAP;
 
     private static final Map<Integer, Integer> DIRECTION_TO_KEYCODE_MAP;
@@ -697,12 +706,7 @@
                     }
                 });
 
-        if (Build.IS_DEBUGGABLE) {
-            AccessibilityServiceInfo serviceInfo = getServiceInfo();
-            // Filter testing KeyEvents from a keyboard.
-            serviceInfo.flags |= FLAG_REQUEST_FILTER_KEY_EVENTS;
-            setServiceInfo(serviceInfo);
-        }
+        updateServiceInfo();
 
         mInputManager = getSystemService(InputManager.class);
 
@@ -711,6 +715,10 @@
 
         // Register an observer to update mTouchInputMethod whenever the user switches IMEs.
         registerInputMethodObserver();
+
+        // Register an observer to update the service info when the developer changes the filter
+        // setting.
+        registerFilterObserver();
     }
 
     @Override
@@ -724,6 +732,7 @@
         getWindowContext().unregisterReceiver(mHomeButtonReceiver);
 
         unregisterInputMethodObserver();
+        unregisterFilterObserver();
         if (mCarInputManager != null) {
             mCarInputManager.releaseInputEventCapture(CarOccupantZoneManager.DISPLAY_TYPE_MAIN);
         }
@@ -911,6 +920,30 @@
     }
 
     /**
+     * Updates this accessibility service's info, enabling or disabling key event filtering
+     * depending on a setting.
+     */
+    private void updateServiceInfo() {
+        AccessibilityServiceInfo serviceInfo = getServiceInfo();
+        if (serviceInfo == null) {
+            L.w("Service info not available");
+            return;
+        }
+        int flags = serviceInfo.flags;
+        boolean filterKeyEvents = Settings.Secure.getInt(getContentResolver(),
+                KEY_ROTARY_KEY_EVENT_FILTER, /* def= */ 0) != 0;
+        if (filterKeyEvents) {
+            flags |= FLAG_REQUEST_FILTER_KEY_EVENTS;
+        } else {
+            flags &= ~FLAG_REQUEST_FILTER_KEY_EVENTS;
+        }
+        if (flags == serviceInfo.flags) return;
+        L.d((filterKeyEvents ? "Enabling" : "Disabling") + " key event filtering");
+        serviceInfo.flags = flags;
+        setServiceInfo(serviceInfo);
+    }
+
+    /**
      * Registers an observer to updates {@link #mTouchInputMethod} whenever the user switches IMEs.
      */
     private void registerInputMethodObserver() {
@@ -947,6 +980,34 @@
         }
     }
 
+    /**
+     * Registers an observer to update our accessibility service info whenever the developer changes
+     * the key event filter setting.
+     */
+    private void registerFilterObserver() {
+        if (mKeyEventFilterObserver != null) {
+            throw new IllegalStateException("Filter observer already registered");
+        }
+        mKeyEventFilterObserver = new ContentObserver(new Handler(Looper.myLooper())) {
+            @Override
+            public void onChange(boolean selfChange) {
+                updateServiceInfo();
+            }
+        };
+        getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(KEY_ROTARY_KEY_EVENT_FILTER),
+                /* notifyForDescendants= */ false,
+                mKeyEventFilterObserver);
+    }
+
+    /** Unregisters the observer registered by {@link #registerFilterObserver}. */
+    private void unregisterFilterObserver() {
+        if (mKeyEventFilterObserver != null) {
+            getContentResolver().unregisterContentObserver(mKeyEventFilterObserver);
+            mKeyEventFilterObserver = null;
+        }
+    }
+
     private static boolean isValidDisplayType(int displayType) {
         if (displayType == CarOccupantZoneManager.DISPLAY_TYPE_MAIN) {
             return true;