Improve robustness of the switch to the touch IME.

1. Save the most recent touch IME in a shared preference so that it
   will persist through RotaryService crashing or being killed.
2. Add a string resource for the default touch IME that the OEM can
   override.

Bug: 160920511
Test: Manual
Change-Id: I0c4daae2819a2fd696721c444752f797ea0efe23
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8b07af9..50cf3b2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -32,6 +32,9 @@
     <!-- Allows us to have an overlay to capture touch events. -->
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 
+    <!-- Allows us to get the username of the current user. -->
+    <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+
     <!-- RotaryService needs to be directBootAware so that it can start before the user is unlocked. -->
     <application>
         <service
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 53ec71d..72f8169 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -15,6 +15,9 @@
   ~ limitations under the License.
   -->
 <resources>
+    <!-- Component name of default touch IME. This resource should be overlaid if a device uses an
+         IME other than CarLatinIME. This resource should not be empty. -->
+    <string name="default_touch_input_method" translatable="false">com.android.inputmethod.latin/.CarLatinIME</string>
     <!-- Component name of rotary IME. Empty if none. -->
     <string name="rotary_input_method" translatable="false"></string>
 </resources>
diff --git a/src/com/android/car/rotary/RotaryService.java b/src/com/android/car/rotary/RotaryService.java
index f9ca967..f72874f 100644
--- a/src/com/android/car/rotary/RotaryService.java
+++ b/src/com/android/car/rotary/RotaryService.java
@@ -51,6 +51,7 @@
 import android.car.input.RotaryEvent;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
@@ -61,6 +62,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.Display;
@@ -122,6 +124,9 @@
      */
     private static final int SHIFT_DETENTS = 10;
 
+    private static final String SHARED_PREFS = "com.android.car.rotary.RotaryService";
+    private static final String TOUCH_INPUT_METHOD_PREFIX = "TOUCH_INPUT_METHOD_";
+
     @NonNull
     private NodeCopier mNodeCopier = new NodeCopier();
 
@@ -214,13 +219,15 @@
     /** Component name of rotary IME. Empty if none. */
     private String mRotaryInputMethod;
 
-    /** Component name of IME used in touch mode. Null until first observed. */
-    @Nullable
+    /** Component name of IME used in touch mode. */
     private String mTouchInputMethod;
 
     /** Observer to update {@link #mTouchInputMethod} when the user switches IMEs. */
     private ContentObserver mInputMethodObserver;
 
+    private SharedPreferences mPrefs;
+    private UserManager mUserManager;
+
     /**
      * Possible actions to do after receiving {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}.
      *
@@ -374,6 +381,11 @@
                 hunRight,
                 showHunOnBottom);
 
+        mPrefs = getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE);
+        mUserManager = getSystemService(UserManager.class);
+        mTouchInputMethod = mPrefs.getString(
+                TOUCH_INPUT_METHOD_PREFIX + mUserManager.getUserName(),
+                res.getString(R.string.default_touch_input_method));
         mRotaryInputMethod = res.getString(R.string.rotary_input_method);
 
         long afterFocusTimeoutMs = res.getInteger(R.integer.after_focus_timeout_ms);
@@ -614,12 +626,16 @@
             @Override
             public void onChange(boolean selfChange) {
                 // Either the user switched input methods or we did. In the former case, update
-                // mTouchInputMethod so we can switch back after switching to the rotary input
-                // method.
+                // mTouchInputMethod and save it so we can switch back after switching to the rotary
+                // input method.
                 String inputMethod =
                         Settings.Secure.getString(contentResolver, DEFAULT_INPUT_METHOD);
                 if (inputMethod != null && !inputMethod.equals(mRotaryInputMethod)) {
                     mTouchInputMethod = inputMethod;
+                    String userName = mUserManager.getUserName();
+                    mPrefs.edit()
+                            .putString(TOUCH_INPUT_METHOD_PREFIX + userName, mTouchInputMethod)
+                            .apply();
                 }
             }
         };
@@ -1747,10 +1763,6 @@
         if (!inRotaryMode) {
             setEditNode(null);
         }
-        if (!inRotaryMode && mTouchInputMethod == null) {
-            L.w("Touch IME not observed");
-            return;
-        }
         // Switch to the rotary IME or the IME in use before we switched to the rotary IME.
         String newIme = inRotaryMode ? mRotaryInputMethod : mTouchInputMethod;
         boolean result =