Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff89b713 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Migrate VirtualKeyboardFragment to DashboardFragment"

parents f1c0f235 74942cee
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@
    android:title="@string/virtual_keyboard_category">
    <!-- Enabled input method list will be populated programmatically here. -->
    <Preference
        android:icon="@drawable/ic_add_24dp"
        android:key="add_virtual_keyboard_screen"
        android:title="@string/add_virtual_keyboard"
        android:order="1000"
        android:fragment="com.android.settings.inputmethod.AvailableVirtualKeyboardFragment"
        settings:searchable="false"/>
        settings:controller="com.android.settings.inputmethod.InputMethodPreferenceController" />
</PreferenceScreen>
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.app.admin.DevicePolicyManager;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;

import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

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.inputmethod.InputMethodPreference;

import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import com.google.common.annotations.VisibleForTesting;

public class InputMethodPreferenceController extends BasePreferenceController implements
        LifecycleObserver, OnStart {

    @VisibleForTesting
    PreferenceScreen mScreen;
    private Preference mPreference;
    private InputMethodManager mImm;
    private DevicePolicyManager mDpm;

    public InputMethodPreferenceController(Context context, String key) {
        super(context, key);
        mImm = context.getSystemService(InputMethodManager.class);
        mDpm = context.getSystemService(DevicePolicyManager.class);
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE_UNSEARCHABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mScreen = screen;
        mPreference = mScreen.findPreference(getPreferenceKey());
    }

    @Override
    public void onStart() {
        updateInputMethodPreferenceViews();
    }

    private void updateInputMethodPreferenceViews() {
        final List<InputMethodPreference> preferenceList = new ArrayList<>();

        final List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
        final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
        final int N = (imis == null ? 0 : imis.size());
        for (int i = 0; i < N; ++i) {
            final InputMethodInfo imi = imis.get(i);
            final boolean isAllowedByOrganization = permittedList == null
                    || permittedList.contains(imi.getPackageName());
            final Drawable icon = imi.loadIcon(mContext.getPackageManager());
            final InputMethodPreference pref = new InputMethodPreference(
                    mScreen.getContext(),
                    imi,
                    false,  /* isImeEnabler */
                    isAllowedByOrganization,
                    null  /* this can be null since isImeEnabler is false */);
            pref.setIcon(icon);
            preferenceList.add(pref);
        }
        final Collator collator = Collator.getInstance();
        preferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
        mScreen.removeAll();
        for (int i = 0; i < N; ++i) {
            final InputMethodPreference pref = preferenceList.get(i);
            pref.setOrder(i);
            mScreen.addPreference(pref);
            pref.updatePreferenceViews();
        }
        mScreen.addPreference(mPreference);
    }
}
+7 −69
Original line number Diff line number Diff line
@@ -16,58 +16,32 @@

package com.android.settings.inputmethod;

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;

import androidx.preference.Preference;

import com.android.internal.util.Preconditions;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtilCompat;
import com.android.settingslib.inputmethod.InputMethodPreference;
import com.android.settingslib.search.SearchIndexable;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@SearchIndexable
public final class VirtualKeyboardFragment extends SettingsPreferenceFragment implements Indexable {

    private static final String ADD_VIRTUAL_KEYBOARD_SCREEN = "add_virtual_keyboard_screen";
public final class VirtualKeyboardFragment extends DashboardFragment {

    private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
    private InputMethodManager mImm;
    private DevicePolicyManager mDpm;
    private Preference mAddVirtualKeyboardScreen;
    private static final String TAG = "VirtualKeyboardFragment";

    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        Activity activity = Preconditions.checkNotNull(getActivity());
        addPreferencesFromResource(R.xml.virtual_keyboard_settings);
        mImm = Preconditions.checkNotNull(activity.getSystemService(InputMethodManager.class));
        mDpm = Preconditions.checkNotNull(activity.getSystemService(DevicePolicyManager.class));
        mAddVirtualKeyboardScreen = Preconditions.checkNotNull(
                findPreference(ADD_VIRTUAL_KEYBOARD_SCREEN));
    protected int getPreferenceScreenResId() {
        return R.xml.virtual_keyboard_settings;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Refresh internal states in mInputMethodSettingValues to keep the latest
        // "InputMethodInfo"s and "InputMethodSubtype"s
        updateInputMethodPreferenceViews();
    protected String getLogTag() {
        return TAG;
    }

    @Override
@@ -75,42 +49,6 @@ public final class VirtualKeyboardFragment extends SettingsPreferenceFragment im
        return SettingsEnums.VIRTUAL_KEYBOARDS;
    }

    private void updateInputMethodPreferenceViews() {
        // Clear existing "InputMethodPreference"s
        mInputMethodPreferenceList.clear();
        List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
        final Context context = getPrefContext();
        final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
        final int N = (imis == null ? 0 : imis.size());
        for (int i = 0; i < N; ++i) {
            final InputMethodInfo imi = imis.get(i);
            final boolean isAllowedByOrganization = permittedList == null
                    || permittedList.contains(imi.getPackageName());
            final Drawable icon = imi.loadIcon(context.getPackageManager());
            final InputMethodPreference pref = new InputMethodPreference(
                    context,
                    imi,
                    false,  /* isImeEnabler */
                    isAllowedByOrganization,
                    null  /* this can be null since isImeEnabler is false */);
            pref.setIcon(icon);
            mInputMethodPreferenceList.add(pref);
        }
        final Collator collator = Collator.getInstance();
        mInputMethodPreferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
        getPreferenceScreen().removeAll();
        for (int i = 0; i < N; ++i) {
            final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
            pref.setOrder(i);
            getPreferenceScreen().addPreference(pref);
            InputMethodAndSubtypeUtilCompat.removeUnnecessaryNonPersistentPreference(pref);
            pref.updatePreferenceViews();
        }
        mAddVirtualKeyboardScreen.setIcon(R.drawable.ic_add_24dp);
        mAddVirtualKeyboardScreen.setOrder(N);
        getPreferenceScreen().addPreference(mAddVirtualKeyboardScreen);
    }

    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider() {
                @Override
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.view.inputmethod.InputMethodInfo;

import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;

import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.List;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowInputMethodManagerWithMethodList.class)
public class InputMethodPreferenceControllerTest {

    private InputMethodPreferenceController mController;
    private Context mContext;
    private PreferenceScreen mScreen;
    private Preference mPreference;

    @Before
    public void setUp() {
        mContext = RuntimeEnvironment.application;
        mScreen = spy(new PreferenceScreen(mContext, null));
        mPreference = new Preference(mContext);
        mController = new InputMethodPreferenceController(mContext, "key");

        when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
        when(mScreen.getContext()).thenReturn(mContext);
        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);

        mController.displayPreference(mScreen);
    }

    @Test
    public void onStart_NoInputMethod_shouldHaveOnePreference() {
        mController.onStart();

        assertThat(mScreen.getPreferenceCount()).isEqualTo(1);
    }

    @Test
    public void onStart_hasInputMethod_shouldHaveCorrectPreferences() {
        final List<InputMethodInfo> imis = new ArrayList<>();
        imis.add(mock(InputMethodInfo.class));
        imis.add(mock(InputMethodInfo.class));
        when(imis.get(0).getPackageName()).thenReturn("name1");
        when(imis.get(1).getPackageName()).thenReturn("name2");
        ShadowInputMethodManagerWithMethodList.getShadow().setEnabledInputMethodList(imis);

        mController.onStart();

        assertThat(mScreen.getPreferenceCount()).isEqualTo(3);
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import java.util.List;
public class ShadowInputMethodManagerWithMethodList extends ShadowInputMethodManager {

    private List<InputMethodInfo> mInputMethodInfos = Collections.emptyList();
    private List<InputMethodInfo> mEnabledInputMethodInfos = Collections.emptyList();

    @Implementation
    public static InputMethodManager getInstance() {
@@ -46,11 +47,26 @@ public class ShadowInputMethodManagerWithMethodList extends ShadowInputMethodMan
        return mInputMethodInfos;
    }

    @Implementation
    protected List<InputMethodInfo> getEnabledInputMethodList() {
        return mEnabledInputMethodInfos;
    }

    @Implementation
    protected List<InputMethodInfo> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
            boolean allowsImplicitlySelectedSubtypes) {
        return Collections.emptyList();
    }

    // Non-Android setter.
    public void setInputMethodList(List<InputMethodInfo> inputMethodInfos) {
        mInputMethodInfos = inputMethodInfos;
    }

    public void setEnabledInputMethodList(List<InputMethodInfo> inputMethodInfos) {
        mEnabledInputMethodInfos = inputMethodInfos;
    }

    public static ShadowInputMethodManagerWithMethodList getShadow() {
        return (ShadowInputMethodManagerWithMethodList) Shadow.extract(
                RuntimeEnvironment.application.getSystemService(InputMethodManager.class));