/* * 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.car.settings.inputmethod; import android.app.admin.DevicePolicyManager; import android.car.drivingstate.CarUxRestrictions; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.util.ArrayMap; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; import com.android.car.settings.common.FragmentController; import com.android.car.settings.common.Logger; import com.android.car.settings.common.PreferenceController; import com.android.car.ui.preference.CarUiPreference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; /** Updates the enabled keyboard list. */ public class EnabledKeyboardPreferenceController extends PreferenceController { private static final Logger LOG = new Logger(EnabledKeyboardPreferenceController.class); private final Map mPreferences = new ArrayMap<>(); private final InputMethodManager mInputMethodManager; private final DevicePolicyManager mDevicePolicyManager; private final PackageManager mPackageManager; public EnabledKeyboardPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions) { super(context, preferenceKey, fragmentController, uxRestrictions); mPackageManager = context.getPackageManager(); mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class); mInputMethodManager = context.getSystemService(InputMethodManager.class); } @Override protected Class getPreferenceType() { return PreferenceGroup.class; } @Override protected void updateState(PreferenceGroup preferenceGroup) { List preferencesToDisplay = new ArrayList<>(); Set preferencesToRemove = new HashSet<>(mPreferences.keySet()); List inputMethodInfos = InputMethodUtil.getPermittedAndEnabledInputMethodList( mInputMethodManager, mDevicePolicyManager); int size = (inputMethodInfos == null) ? 0 : inputMethodInfos.size(); for (int i = 0; i < size; ++i) { InputMethodInfo inputMethodInfo = inputMethodInfos.get(i); Preference preference = createPreference(inputMethodInfo); if (mPreferences.containsKey(preference.getKey())) { Preference displayedPreference = mPreferences.get(preference.getKey()); if (arePreferencesDifferent(displayedPreference, preference)) { preferencesToDisplay.add(preference); } else { preferencesToRemove.remove(preference.getKey()); } } else { preferencesToDisplay.add(preference); } } updatePreferenceGroup(preferenceGroup, preferencesToDisplay, preferencesToRemove); } private void updatePreferenceGroup( PreferenceGroup preferenceGroup, List preferencesToDisplay, Set preferencesToRemove) { Collections.sort(preferencesToDisplay, Comparator.comparing( (Preference a) -> a.getTitle().toString()) .thenComparing((Preference a) -> a.getSummary().toString())); for (String key : preferencesToRemove) { preferenceGroup.removePreference(mPreferences.get(key)); mPreferences.remove(key); } for (int i = 0; i < preferencesToDisplay.size(); ++i) { Preference pref = preferencesToDisplay.get(i); pref.setOrder(i); mPreferences.put(pref.getKey(), pref); preferenceGroup.addPreference(pref); } } /** * Creates a preference. */ private Preference createPreference(InputMethodInfo inputMethodInfo) { CarUiPreference preference = new CarUiPreference(getContext()); preference.setKey(String.valueOf(inputMethodInfo.hashCode())); preference.setIcon(InputMethodUtil.getPackageIcon(mPackageManager, inputMethodInfo)); preference.setTitle(InputMethodUtil.getPackageLabel(mPackageManager, inputMethodInfo)); preference.setSummary(InputMethodUtil.getSummaryString( getContext(), mInputMethodManager, inputMethodInfo)); preference.setOnPreferenceClickListener(pref -> { try { String settingsActivity = inputMethodInfo.getSettingsActivity(); if (settingsActivity == null) { LOG.d("IME's Settings Activity not defined."); return true; } Intent intent = createInputMethodSettingsIntent(inputMethodInfo.getPackageName(), settingsActivity); // Invoke a settings activity of an input method. getContext().startActivity(intent); } catch (final ActivityNotFoundException e) { LOG.d("IME's Settings Activity Not Found. " + e); } return true; }); return preference; } @VisibleForTesting Intent createInputMethodSettingsIntent(String packageName, String settingsActivity) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName(packageName, settingsActivity); return intent; } private boolean arePreferencesDifferent(Preference lhs, Preference rhs) { return !Objects.equals(lhs.getTitle(), rhs.getTitle()) || !Objects.equals(lhs.getSummary(), rhs.getSummary()); } }