1 /* 2 * Copyright (C) 2022 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.tv.settings.customization; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.graphics.drawable.Drawable; 22 import android.util.Log; 23 24 import androidx.preference.Preference; 25 26 import com.android.tv.twopanelsettings.slices.SlicePreference; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * Reads the preference meta-data provided in the customization apk and builds 33 * the listed preferences if any. 34 */ 35 final class PartnerResourcesParser { 36 private static final String TAG = "PartnerResourcesParser"; 37 38 private final Context mContext; 39 private final String mSettingsScreen; 40 41 static final String PREFERENCE_GROUP_END_INDICATOR = "="; 42 43 /** 44 * Create an instance of the parser for the particular settings screen 45 * @param context TvSettings application context 46 * @param settingsScreen String identifier for the settings screen for which 47 * the meta data has to be read 48 */ PartnerResourcesParser(Context context, String settingsScreen)49 PartnerResourcesParser(Context context, String settingsScreen) { 50 mContext = context; 51 mSettingsScreen = settingsScreen; 52 } 53 buildPreferences()54 public List<Preference> buildPreferences() { 55 final Integer numberOfPreferences = Partner.getInstance(mContext) 56 .getInteger(String.format("%s_num_prefs", mSettingsScreen)); 57 if (numberOfPreferences == null) { 58 Log.i(TAG, "Number of new preferences not provided"); 59 return new ArrayList<>(); 60 } 61 final List<Preference> preferences = new ArrayList<>(numberOfPreferences); 62 for (int i = 1; i <= numberOfPreferences; i++) { 63 final String name = String.format("%s_pref%d", mSettingsScreen, i); 64 final String uri = Partner.getInstance(mContext).getString( 65 String.format("%s_uri", name)); 66 final String action = Partner.getInstance(mContext).getString( 67 String.format("%s_intent_action", name)); 68 if (uri == null && action == null) { 69 Log.i(TAG, "Invalid preference, missing uri and action"); 70 continue; 71 } 72 if (uri != null) { 73 preferences.add(buildSlicePreference(name, uri)); 74 } else { 75 preferences.add(buildPreference(name, action)); 76 } 77 } 78 return preferences; 79 } 80 buildSlicePreference(String name, String uri)81 private SlicePreference buildSlicePreference(String name, String uri) { 82 SlicePreference slicePreference = new SlicePreference(mContext); 83 slicePreference.setUri(uri); 84 final String contentDescription = Partner.getInstance(mContext).getString( 85 String.format("%s_content_description", name)); 86 if (contentDescription != null) { 87 slicePreference.setContentDescription(contentDescription); 88 } 89 parseGenericPreferenceAttributes(name, slicePreference); 90 return slicePreference; 91 } 92 parseGenericPreferenceAttributes(String name, Preference preference)93 private void parseGenericPreferenceAttributes(String name, Preference preference) { 94 preference.setKey(Partner.getInstance(mContext).getString( 95 String.format("%s_key", name))); 96 final Drawable icon = Partner.getInstance(mContext).getDrawable( 97 String.format("%s_icon", name), mContext.getTheme()); 98 if (icon != null) { 99 preference.setIcon(icon); 100 } 101 final String title = Partner.getInstance(mContext).getString( 102 String.format("%s_title", name)); 103 if (title != null) { 104 preference.setTitle(title); 105 } 106 final String summary = Partner.getInstance(mContext).getString( 107 String.format("%s_summary", name)); 108 if (summary != null) { 109 preference.setSummary(summary); 110 } 111 } 112 buildPreference(String name, String action)113 private Preference buildPreference(String name, String action) { 114 final Intent intent = new Intent(); 115 intent.setAction(action); 116 final String targetPackage = Partner.getInstance(mContext).getString( 117 String.format("%s_intent_target_package", name)); 118 if (targetPackage != null) { 119 intent.setPackage(targetPackage); 120 final String targetClass = Partner.getInstance(mContext).getString( 121 String.format("%s_intent_target_class", name)); 122 if (targetClass != null) { 123 intent.setClassName(targetPackage, targetClass); 124 } 125 } 126 final Preference preference = new Preference(mContext); 127 preference.setIntent(intent); 128 parseGenericPreferenceAttributes(name, preference); 129 return preference; 130 } 131 getOrderedPreferences()132 String[] getOrderedPreferences() { 133 final List<String> orderedPreferences = new ArrayList<>(); 134 iteratePreferences(orderedPreferences, 135 String.format("%s_preferences", mSettingsScreen)); 136 return orderedPreferences.toArray(String[]::new); 137 } 138 iteratePreferences(List<String> orderedPreferences, String preferencesResource)139 private void iteratePreferences(List<String> orderedPreferences, String preferencesResource) { 140 final String[] preferences = Partner.getInstance(mContext).getArray(preferencesResource); 141 if (preferences == null) { 142 Log.i(TAG, "Ordered preference list not found"); 143 return; 144 } 145 for (final String preference : preferences) { 146 orderedPreferences.add(preference); 147 // Check to see if it is a PreferenceGroup, in which case, recursively 148 // iterate through the PreferenceGroup to list all its Preferences 149 final String nestedPreferencesResource = String.format( 150 "%s_%s_preferences", mSettingsScreen, preference); 151 final String[] nestedPreferences = Partner.getInstance(mContext) 152 .getArray(nestedPreferencesResource); 153 if (nestedPreferences != null && nestedPreferences.length > 0) { 154 iteratePreferences(orderedPreferences, nestedPreferencesResource); 155 } 156 } 157 // This is necessary to know when a nested PreferenceGroup ends 158 // so the preferences after this are correctly added to the 159 // parent PreferenceGroup 160 orderedPreferences.add(PREFERENCE_GROUP_END_INDICATOR); 161 } 162 } 163