1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.settings.common; 18 19 import static com.android.car.settings.common.ExtraSettingsLoader.META_DATA_IS_TOP_LEVEL_EXTRA_SETTINGS; 20 21 import android.car.drivingstate.CarUxRestrictions; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Bundle; 25 import android.provider.Settings; 26 import android.text.TextUtils; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.view.ViewGroup; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 import androidx.annotation.VisibleForTesting; 34 import androidx.annotation.XmlRes; 35 import androidx.fragment.app.Fragment; 36 import androidx.preference.Preference; 37 import androidx.preference.PreferenceScreen; 38 39 import com.android.car.settings.R; 40 import com.android.car.settings.activityembedding.ActivityEmbeddingUtils; 41 import com.android.car.settings.common.CarSettingActivities.HomepageActivity; 42 import com.android.car.ui.recyclerview.CarUiRecyclerView; 43 import com.android.car.ui.toolbar.MenuItem; 44 import com.android.car.ui.toolbar.NavButtonMode; 45 import com.android.car.ui.toolbar.ToolbarController; 46 47 import java.util.Collections; 48 import java.util.List; 49 50 /** 51 * Top level settings menu. 52 */ 53 public class TopLevelMenuFragment extends SettingsFragment { 54 55 /** 56 * The preference key for the top-level menu item associated with a fragment. 57 * This is intended to be included with fragments launched from top-level menu 58 * preferences using the {@link #launchFragment} method. 59 */ 60 public static final String FRAGMENT_MENU_PREFERENCE_KEY = "fragment_menu_preference_key"; 61 62 private static final String KEY_SAVED_SELECTED_PREFERENCE_KEY = "saved_selected_preference_key"; 63 64 private MenuItem mSearchButton; 65 private String mSelectedPreferenceKey; 66 67 @Override 68 @XmlRes getPreferenceScreenResId()69 protected int getPreferenceScreenResId() { 70 return R.xml.homepage_fragment; 71 } 72 73 @Override getToolbarMenuItems()74 protected List<MenuItem> getToolbarMenuItems() { 75 return Collections.singletonList(mSearchButton); 76 } 77 78 @Override onCreate(Bundle savedInstanceState)79 public void onCreate(Bundle savedInstanceState) { 80 super.onCreate(savedInstanceState); 81 mSearchButton = new MenuItem.Builder(getContext()) 82 .setToSearch() 83 .setOnClickListener(i -> onSearchButtonClicked()) 84 .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD) 85 .build(); 86 } 87 88 @Override onResume()89 public void onResume() { 90 super.onResume(); 91 updatePreferenceHighlight(getHeaderKeyFromActivity()); 92 } 93 94 @Override setupToolbar(@onNull ToolbarController toolbar)95 protected void setupToolbar(@NonNull ToolbarController toolbar) { 96 super.setupToolbar(toolbar); 97 toolbar.setTitle(R.string.settings_label); 98 if (ActivityEmbeddingUtils.isEmbeddingSplitActivated(getActivity())) { 99 toolbar.setLogo(R.drawable.ic_launcher_settings); 100 toolbar.setNavButtonMode(NavButtonMode.DISABLED); 101 } else { 102 toolbar.setLogo(null); 103 toolbar.setNavButtonMode(NavButtonMode.BACK); 104 } 105 } 106 107 @Override onViewCreated(@onNull View view, @Nullable Bundle savedInstanceState)108 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 109 super.onViewCreated(view, savedInstanceState); 110 if (getToolbar() != null) { 111 setupToolbar(getToolbar()); 112 } 113 if (savedInstanceState != null 114 && savedInstanceState.getString(KEY_SAVED_SELECTED_PREFERENCE_KEY) != null) { 115 updatePreferenceHighlight( 116 savedInstanceState.getString(KEY_SAVED_SELECTED_PREFERENCE_KEY)); 117 } else { 118 if (mSelectedPreferenceKey != null) { 119 updatePreferenceHighlight(mSelectedPreferenceKey); 120 } else { 121 updatePreferenceHighlight(getHeaderKeyFromActivity()); 122 } 123 } 124 } 125 126 @Nullable getHeaderKeyFromActivity()127 private String getHeaderKeyFromActivity() { 128 if (getActivity() == null || !(getActivity() instanceof HomepageActivity)) { 129 return null; 130 } 131 return ((HomepageActivity) getActivity()).getTopLevelHeaderKey(); 132 } 133 setSelectedPreferenceKey(@ullable String key)134 private void setSelectedPreferenceKey(@Nullable String key) { 135 mSelectedPreferenceKey = key; 136 if (getActivity() != null && getActivity() instanceof HomepageActivity) { 137 ((HomepageActivity) getActivity()).setTopLevelHeaderKey(key); 138 } 139 } 140 141 @Override onSaveInstanceState(@onNull Bundle outState)142 public void onSaveInstanceState(@NonNull Bundle outState) { 143 super.onSaveInstanceState(outState); 144 setSelectedPreferenceKey(mSelectedPreferenceKey); 145 outState.putString(KEY_SAVED_SELECTED_PREFERENCE_KEY, mSelectedPreferenceKey); 146 } 147 148 @Override onCreateCarUiRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)149 public CarUiRecyclerView onCreateCarUiRecyclerView(LayoutInflater inflater, ViewGroup parent, 150 Bundle savedInstanceState) { 151 inflater.inflate(R.layout.top_level_recyclerview, parent, /* attachToRoot= */ true); 152 return parent.findViewById(R.id.top_level_recycler_view); 153 } 154 155 @Override launchFragment(@ullable Fragment fragment)156 public void launchFragment(@Nullable Fragment fragment) { 157 if (fragment == null) { 158 return; 159 } 160 String preferenceKey = null; 161 if (fragment.getArguments() != null) { 162 preferenceKey = fragment.getArguments().getString(FRAGMENT_MENU_PREFERENCE_KEY); 163 } 164 updatePreferenceHighlight(preferenceKey); 165 super.launchFragment(fragment); 166 } 167 168 @Override onPreferenceTreeClick(Preference preference)169 public boolean onPreferenceTreeClick(Preference preference) { 170 if (preference.getFragment() == null 171 && !preference.getExtras().getBoolean(META_DATA_IS_TOP_LEVEL_EXTRA_SETTINGS)) { 172 // Launching a new activity that is not a top level injected settings 173 return super.onPreferenceTreeClick(preference); 174 } 175 updatePreferenceHighlight(preference.getKey()); 176 return super.onPreferenceTreeClick(preference); 177 } 178 @Override createHighlightableAdapter( PreferenceScreen preferenceScreen)179 protected HighlightablePreferenceGroupAdapter createHighlightableAdapter( 180 PreferenceScreen preferenceScreen) { 181 return new HighlightablePreferenceGroupAdapter(preferenceScreen, 182 R.drawable.top_level_preference_background, 183 R.drawable.top_level_preference_highlight); 184 } 185 updatePreferenceHighlight(String key)186 private void updatePreferenceHighlight(String key) { 187 setSelectedPreferenceKey(key); 188 if (!TextUtils.isEmpty(mSelectedPreferenceKey)) { 189 requestPreferenceHighlight(mSelectedPreferenceKey); 190 } else { 191 clearPreferenceHighlight(); 192 } 193 } 194 195 @VisibleForTesting getSelectedPreferenceKey()196 String getSelectedPreferenceKey() { 197 return mSelectedPreferenceKey; 198 } 199 onSearchButtonClicked()200 private void onSearchButtonClicked() { 201 Intent intent = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS) 202 .setPackage(getSettingsIntelligencePkgName(getContext())); 203 if (intent.resolveActivity(getContext().getPackageManager()) == null) { 204 return; 205 } 206 startActivity(intent); 207 } 208 getSettingsIntelligencePkgName(Context context)209 private String getSettingsIntelligencePkgName(Context context) { 210 return context.getString(R.string.config_settingsintelligence_package_name); 211 } 212 } 213