1 /* 2 * Copyright (C) 2023 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.device.eco; 18 19 import static android.Manifest.permission.MANAGE_LOW_POWER_STANDBY; 20 21 import android.content.ContentProvider; 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.database.Cursor; 25 import android.graphics.drawable.Icon; 26 import android.net.Uri; 27 import android.os.Binder; 28 import android.os.Bundle; 29 30 import androidx.annotation.NonNull; 31 import androidx.annotation.Nullable; 32 33 import com.android.tv.settings.device.eco.EnergyModesHelper.EnergyMode; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * ContentProvider that provides methods to query and set Energy Modes. 40 */ 41 public class EnergyModesContentProvider extends ContentProvider { 42 /** Method to get available energy modes, default mode, and selected mode */ 43 private static final String METHOD_GET_ENERGY_MODES = "getEnergyModes"; 44 45 /** 46 * Method to set the selected energy mode. 47 * Requires permission MANAGE_LOW_POWER_STANDBY. 48 */ 49 private static final String METHOD_SET_ENERGY_MODE = "setEnergyMode"; 50 51 /** Key for a String representing the identifier of the default mode (may be null). */ 52 private static final String KEY_DEFAULT_MODE = "default_mode"; 53 54 /** Key for a String representing the currently selected mode. */ 55 private static final String KEY_SELECTED_MODE = "selected_mode"; 56 57 /** Key for a List of Bundle representing the available energy modes. */ 58 private static final String KEY_ENERGY_MODES = "energy_modes"; 59 60 /** Key for a String representing the identifier for an energy mode. */ 61 private static final String KEY_IDENTIFIER = "identifier"; 62 63 /** Key for an Icon representing the icon of an energy mode. */ 64 private static final String KEY_ICON = "icon"; 65 66 /** Key for an int representing the color of an energy mode (in ARGB). */ 67 private static final String KEY_COLOR = "color"; 68 69 /** Key for a String representing the title of an energy mode. */ 70 private static final String KEY_TITLE = "title"; 71 72 /** Key for a String representing the subtitle of an energy mode. */ 73 private static final String KEY_SUBTITLE = "subtitle"; 74 75 /** Key for a String representing the description of an energy mode. */ 76 private static final String KEY_DESCRIPTION = "description"; 77 78 /** Key for a String representing a short description of an energy mode. */ 79 private static final String KEY_SHORT_DESCRIPTION = "short_description"; 80 81 /** Key for a String array representing the (human-friendly) features of an energy mode. */ 82 private static final String KEY_FEATURES_LIST = "features_list"; 83 84 /** Key for a String array representing the features of an energy mode. */ 85 private static final String KEY_FEATURES = "features"; 86 87 @Override onCreate()88 public boolean onCreate() { 89 return true; 90 } 91 92 @Nullable 93 @Override query(@onNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder)94 public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, 95 @Nullable String[] selectionArgs, @Nullable String sortOrder) { 96 throw new UnsupportedOperationException("query operation not supported currently."); 97 } 98 99 @Nullable 100 @Override getType(@onNull Uri uri)101 public String getType(@NonNull Uri uri) { 102 throw new UnsupportedOperationException("getType operation not supported currently."); 103 } 104 105 @Nullable 106 @Override insert(@onNull Uri uri, @Nullable ContentValues values)107 public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 108 throw new UnsupportedOperationException("insert operation not supported currently."); 109 } 110 111 @Override delete(@onNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs)112 public int delete(@NonNull Uri uri, @Nullable String selection, 113 @Nullable String[] selectionArgs) { 114 throw new UnsupportedOperationException("delete operation not supported currently."); 115 } 116 117 @Override update(@onNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs)118 public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, 119 @Nullable String[] selectionArgs) { 120 throw new UnsupportedOperationException("update operation not supported currently."); 121 } 122 123 @Override call(String method, String arg, Bundle extras)124 public Bundle call(String method, String arg, Bundle extras) { 125 if (METHOD_GET_ENERGY_MODES.equals(method)) { 126 return getEnergyModesFromBinder(); 127 } else if (METHOD_SET_ENERGY_MODE.equals(method)) { 128 return setEnergyModeFromBinder(arg); 129 } 130 131 throw new IllegalArgumentException("Unknown method name"); 132 } 133 getEnergyModesFromBinder()134 private Bundle getEnergyModesFromBinder() { 135 final long ident = Binder.clearCallingIdentity(); 136 try { 137 return getEnergyModes(); 138 } finally { 139 Binder.restoreCallingIdentity(ident); 140 } 141 } 142 getEnergyModes()143 private Bundle getEnergyModes() { 144 EnergyModesHelper energyModesHelper = new EnergyModesHelper(getContext()); 145 146 final EnergyMode defaultMode = energyModesHelper.getDefaultEnergyMode(); 147 final EnergyMode currentMode = energyModesHelper.updateEnergyMode(); 148 149 Bundle bundle = new Bundle(); 150 bundle.putString(KEY_DEFAULT_MODE, getModeIdentifier(defaultMode)); 151 bundle.putString(KEY_SELECTED_MODE, getModeIdentifier(currentMode)); 152 bundle.putParcelableList(KEY_ENERGY_MODES, getModes(energyModesHelper)); 153 return bundle; 154 } 155 setEnergyModeFromBinder(String identifier)156 private Bundle setEnergyModeFromBinder(String identifier) { 157 getContext().enforceCallingOrSelfPermission(MANAGE_LOW_POWER_STANDBY, null); 158 final long ident = Binder.clearCallingIdentity(); 159 try { 160 EnergyModesHelper energyModesHelper = new EnergyModesHelper(getContext()); 161 EnergyMode energyMode = energyModesHelper.getEnergyMode(/* identifier= */ identifier); 162 if (energyMode == null) { 163 throw new IllegalArgumentException("Unknown energy mode: " + identifier); 164 } 165 166 energyModesHelper.setEnergyMode(energyMode); 167 } finally { 168 Binder.restoreCallingIdentity(ident); 169 } 170 171 return null; 172 } 173 174 @Nullable getModeIdentifier(@ullable EnergyMode mode)175 private String getModeIdentifier(@Nullable EnergyMode mode) { 176 if (mode == null) { 177 return null; 178 } 179 180 return getContext().getString(mode.identifierRes); 181 } 182 183 @NonNull getModes(@onNull EnergyModesHelper helper)184 private List<Bundle> getModes(@NonNull EnergyModesHelper helper) { 185 final List<Bundle> result = new ArrayList<>(); 186 final List<EnergyMode> energyModes = helper.getEnergyModes(); 187 188 for (EnergyMode mode : energyModes) { 189 result.add(convertEnergyModeToBundle(helper, mode)); 190 } 191 192 return result; 193 } 194 195 @NonNull convertEnergyModeToBundle( @onNull EnergyModesHelper helper, @NonNull EnergyMode mode)196 private Bundle convertEnergyModeToBundle( 197 @NonNull EnergyModesHelper helper, @NonNull EnergyMode mode) { 198 Context context = getContext(); 199 Bundle bundle = new Bundle(); 200 201 bundle.putString(KEY_IDENTIFIER, getModeIdentifier(mode)); 202 bundle.putParcelable(KEY_ICON, Icon.createWithResource(context, mode.iconRes)); 203 bundle.putInt(KEY_COLOR, context.getColor(mode.colorRes)); 204 bundle.putString(KEY_TITLE, context.getString(mode.titleRes)); 205 bundle.putString(KEY_SUBTITLE, context.getString(mode.subtitleRes)); 206 bundle.putString(KEY_DESCRIPTION, context.getString(mode.infoTextRes)); 207 bundle.putString(KEY_SHORT_DESCRIPTION, context.getString(mode.infoTextRes)); 208 bundle.putStringArray(KEY_FEATURES_LIST, 209 context.getResources().getStringArray(mode.featuresRes)); 210 bundle.putStringArray(KEY_FEATURES, 211 helper.getAllowedFeatures(mode).toArray(new String[0])); 212 213 return bundle; 214 } 215 } 216