diff --git a/res/xml/input_methods_subtype.xml b/res/xml/input_methods_subtype.xml
new file mode 100644
index 00000000000..643e93acb02
--- /dev/null
+++ b/res/xml/input_methods_subtype.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
index 37f64133915..f3540893649 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java
@@ -16,17 +16,18 @@
package com.android.settings.inputmethod;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import androidx.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settingslib.inputmethod.InputMethodAndSubtypeEnablerManager;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
-public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
- private InputMethodAndSubtypeEnablerManager mManager;
+public class InputMethodAndSubtypeEnabler extends DashboardFragment {
+
+ private static final String TAG = "InputMethodAndSubtypeEnabler";
@Override
public int getMetricsCategory() {
@@ -34,8 +35,18 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
}
@Override
- public void onCreate(final Bundle icicle) {
- super.onCreate(icicle);
+ protected int getPreferenceScreenResId() {
+ return R.xml.input_methods_subtype;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
// Input method id should be available from an Intent when this preference is launched as a
// single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available
@@ -44,11 +55,8 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
final String targetImi = getStringExtraFromIntentOrArguments(
android.provider.Settings.EXTRA_INPUT_METHOD_ID);
- final PreferenceScreen root =
- getPreferenceManager().createPreferenceScreen(getPrefContext());
- mManager = new InputMethodAndSubtypeEnablerManager(this);
- mManager.init(this, targetImi, root);
- setPreferenceScreen(root);
+ use(InputMethodAndSubtypePreferenceController.class).initialize(this /* fragment */,
+ targetImi);
}
private String getStringExtraFromIntentOrArguments(final String name) {
@@ -69,16 +77,4 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
getActivity().setTitle(title);
}
}
-
- @Override
- public void onResume() {
- super.onResume();
- mManager.refresh(getContext(), this);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mManager.save(getContext(), this);
- }
}
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceController.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceController.java
new file mode 100644
index 00000000000..625289ccc06
--- /dev/null
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceController.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeEnablerManager;
+
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+
+public class InputMethodAndSubtypePreferenceController extends BasePreferenceController implements
+ LifecycleObserver, OnStart, OnStop {
+
+ private PreferenceFragment mFragment;
+ private InputMethodAndSubtypeEnablerManager mManager;
+ private String mTargetImi;
+
+ public InputMethodAndSubtypePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void initialize(PreferenceFragment fragment, String imi) {
+ mFragment = fragment;
+ mTargetImi = imi;
+ mManager = new InputMethodAndSubtypeEnablerManager(mFragment);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mManager.init(mFragment, mTargetImi, screen);
+ }
+
+ @Override
+ public void onStart() {
+ mManager.refresh(mContext, mFragment);
+ }
+
+ @Override
+ public void onStop() {
+ mManager.save(mContext, mFragment);
+ }
+}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index e6744ded37d..8bd4f823840 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -27,3 +27,4 @@ com.android.settings.notification.ZenModeEventRuleSettings
com.android.settings.notification.ZenModeScheduleRuleSettings
com.android.settings.fuelgauge.RestrictedAppDetails
com.android.settings.datetime.timezone.TimeZoneSettings
+com.android.settings.inputmethod.InputMethodAndSubtypeEnabler
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index 8523b2f1ab9..a72cd500df6 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -28,7 +28,6 @@ com.android.settings.accessibility.ToggleScreenReaderPreferenceFragmentForSetupW
com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetupWizard
com.android.settings.accounts.AccountSyncSettings
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
-com.android.settings.inputmethod.InputMethodAndSubtypeEnabler
com.android.settings.applications.appinfo.DrawOverlayDetails
com.android.settings.backup.ToggleBackupSettingFragment
com.android.settings.users.UserDetailsSettings
diff --git a/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerTest.java b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerTest.java
new file mode 100644
index 00000000000..ffb726ae4c4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class InputMethodAndSubtypeEnablerTest {
+
+ private Activity mActivity;
+ private InputMethodAndSubtypeEnabler mFragment;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mActivity = Robolectric.setupActivity(Activity.class);
+ mFragment = spy(new InputMethodAndSubtypeEnabler());
+ when(mFragment.getActivity()).thenReturn(mActivity);
+ }
+
+ @Test
+ public void onActivityCreated_shouldUpdateTitleFromArgument() {
+ final String test = "title1";
+ final Bundle args = new Bundle();
+ args.putString(Intent.EXTRA_TITLE, test);
+ mFragment.setArguments(args);
+
+ mFragment.onActivityCreated(null);
+
+ assertThat(mFragment.getActivity().getTitle()).isEqualTo(test);
+ }
+
+ @Test
+ public void onActivityCreated_shouldUpdateTitleFromIntent() {
+ final String test = "title1";
+ final Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_TITLE, test);
+ mActivity.setIntent(intent);
+
+ mFragment.onActivityCreated(null);
+
+ assertThat(mFragment.getActivity().getTitle()).isEqualTo(test);
+ }
+
+ @Test
+ public void getPreferenceScreenResId_shouldReturnXml() {
+ assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.input_methods_subtype);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java
new file mode 100644
index 00000000000..7e977787cf3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowInputMethodManagerWithMethodList.class)
+public class InputMethodAndSubtypePreferenceControllerTest {
+
+ @Mock
+ private PreferenceFragment mFragment;
+ private Context mContext;
+ private InputMethodAndSubtypePreferenceController mController;
+ private PreferenceManager mPreferenceManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPreferenceManager = new PreferenceManager(mContext);
+ when(mFragment.getContext()).thenReturn(mContext);
+ when(mFragment.getResources()).thenReturn(mContext.getResources());
+ when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
+ mController = new InputMethodAndSubtypePreferenceController(mContext, "pref_key");
+ mController.initialize(mFragment, "");
+ }
+
+ @Test
+ public void isAlwaysAvailable() {
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void displayPreference_hasInputMethodSubType_shouldAddPreference() {
+ final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+
+ mController.displayPreference(screen);
+
+ assertThat(screen.getPreferenceCount()).isEqualTo(0);
+
+ final List imis = new ArrayList<>();
+ imis.add(createInputMethodInfo("test", mContext));
+ ShadowInputMethodManagerWithMethodList.getShadow().setInputMethodList(imis);
+
+ mController.initialize(mFragment, "");
+ mController.displayPreference(screen);
+
+ assertThat(screen.getPreferenceCount()).isEqualTo(2);
+ }
+
+ private InputMethodInfo createInputMethodInfo(final String name, Context targetContext) {
+ List subtypes = new ArrayList<>();
+
+ subtypes.add(new InputMethodSubtype.InputMethodSubtypeBuilder()
+ .build());
+ subtypes.add(new InputMethodSubtype.InputMethodSubtypeBuilder()
+ .build());
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = new ServiceInfo();
+ resolveInfo.serviceInfo.packageName = "com.android.ime";
+ resolveInfo.serviceInfo.name = name;
+ resolveInfo.serviceInfo.applicationInfo = new ApplicationInfo();
+ resolveInfo.serviceInfo.applicationInfo.enabled = true;
+
+ return new InputMethodInfo(
+ resolveInfo,
+ false /* isAuxIme */,
+ "SettingsActivity",
+ subtypes,
+ 0 /* isDefaultResId */,
+ true /* forceDefault */);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputMethodManagerWithMethodList.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputMethodManagerWithMethodList.java
index 0e59fec30ce..0b7d69ba3a6 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputMethodManagerWithMethodList.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputMethodManagerWithMethodList.java
@@ -19,8 +19,10 @@ package com.android.settings.testutils.shadow;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowInputMethodManager;
import java.util.Collections;
@@ -48,4 +50,9 @@ public class ShadowInputMethodManagerWithMethodList extends ShadowInputMethodMan
public void setInputMethodList(List inputMethodInfos) {
mInputMethodInfos = inputMethodInfos;
}
+
+ public static ShadowInputMethodManagerWithMethodList getShadow() {
+ return (ShadowInputMethodManagerWithMethodList) Shadow.extract(
+ RuntimeEnvironment.application.getSystemService(InputMethodManager.class));
+ }
}