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.qc; 18 19 import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING_FOR_ZONE; 20 import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_ZONE; 21 import static com.android.car.settings.common.PreferenceController.HIDDEN_FOR_ZONE; 22 import static com.android.car.settings.common.PreferenceXmlParser.PREF_AVAILABILITY_STATUS_HIDDEN; 23 import static com.android.car.settings.common.PreferenceXmlParser.PREF_AVAILABILITY_STATUS_READ; 24 25 import android.app.PendingIntent; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.net.Uri; 29 import android.os.Bundle; 30 31 import com.android.car.qc.QCItem; 32 33 import java.lang.reflect.Constructor; 34 import java.lang.reflect.InvocationTargetException; 35 36 /** 37 * Base class for QCItems provided by CarSettings. 38 */ 39 public abstract class SettingsQCItem { 40 41 private final Context mContext; 42 private int mAvailabilityStatusForZone; 43 SettingsQCItem(Context context)44 public SettingsQCItem(Context context) { 45 mContext = context; 46 } 47 setAvailabilityStatusForZone(String availabilityStatusForZone)48 protected void setAvailabilityStatusForZone(String availabilityStatusForZone) { 49 if (PREF_AVAILABILITY_STATUS_READ.equals(availabilityStatusForZone)) { 50 mAvailabilityStatusForZone = AVAILABLE_FOR_VIEWING_FOR_ZONE; 51 } else if (PREF_AVAILABILITY_STATUS_HIDDEN.equals(availabilityStatusForZone)) { 52 mAvailabilityStatusForZone = HIDDEN_FOR_ZONE; 53 } else { 54 mAvailabilityStatusForZone = AVAILABLE_FOR_ZONE; 55 } 56 } 57 58 /** 59 * @return an complete instance of the {@link QCItem}. 60 */ getQCItem()61 abstract QCItem getQCItem(); 62 63 /** 64 * @return a {@link android.content.ContentResolver#SCHEME_CONTENT content} {@link Uri} which 65 * backs the {@link QCItem} returned by {@link #getQCItem()}. 66 */ getUri()67 abstract Uri getUri(); 68 69 /** 70 * @return the context for the {@link SettingsQCItem}. 71 */ getContext()72 protected Context getContext() { 73 return mContext; 74 } 75 76 /** 77 * @return a boolean that indicates whether the QCItem is hidden for the current zone. 78 */ isHiddenForZone()79 protected boolean isHiddenForZone() { 80 return mAvailabilityStatusForZone == HIDDEN_FOR_ZONE; 81 } 82 83 /** 84 * @return a boolean that indicates whether the QCItem is only readable for the current zone. 85 */ isReadOnlyForZone()86 protected boolean isReadOnlyForZone() { 87 return mAvailabilityStatusForZone == AVAILABLE_FOR_VIEWING_FOR_ZONE; 88 } 89 90 /** 91 * @return a boolean that indicates whether the QCItem is writable for the current zone. 92 */ isWritableForZone()93 protected boolean isWritableForZone() { 94 return mAvailabilityStatusForZone == AVAILABLE_FOR_ZONE; 95 } 96 97 /** 98 * Handles the actions sent by the {@link Intent intents} bound to the {@link QCItem} returned 99 * by {@link #getQCItem()}. 100 * 101 * @param intent which has the action taken on a {@link QCItem}. 102 */ onNotifyChange(Intent intent)103 void onNotifyChange(Intent intent) {} 104 105 /** 106 * Standardize the primary intent for the QCItem. 107 */ getActivityIntent(Intent intent)108 PendingIntent getActivityIntent(Intent intent) { 109 return PendingIntent.getActivity(getContext(), 110 0 /* requestCode */, intent, 111 PendingIntent.FLAG_IMMUTABLE); 112 } 113 114 /** 115 * See {@link #getBroadcastIntent(Bundle, int)} 116 */ getBroadcastIntent()117 PendingIntent getBroadcastIntent() { 118 return getBroadcastIntent(/* extras= */ null); 119 } 120 121 /** 122 * See {@link #getBroadcastIntent(Bundle, int)} 123 */ getBroadcastIntent(Bundle extras)124 PendingIntent getBroadcastIntent(Bundle extras) { 125 return getBroadcastIntent(extras, /* requestCode= */ 0); 126 } 127 128 /** 129 * Standardize the intents returned to indicate actions by the QCItem. 130 * <p> 131 * The {@link PendingIntent} is linked to {@link SettingsQCBroadcastReceiver} where the 132 * Intent Action is found by {@code getUri().toString()}. 133 * 134 * @return a {@link PendingIntent} linked to {@link SettingsQCBroadcastReceiver}. 135 */ getBroadcastIntent(Bundle extras, int requestCode)136 PendingIntent getBroadcastIntent(Bundle extras, int requestCode) { 137 Intent intent = new Intent(getUri().toString()) 138 .setData(getUri()) 139 .setClass(getContext(), SettingsQCBroadcastReceiver.class) 140 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 141 if (extras != null) { 142 intent.putExtras(extras); 143 } 144 return PendingIntent.getBroadcast(getContext(), requestCode, intent, 145 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 146 } 147 148 /** 149 * Build an instance of a {@link SettingsQCItem} which has a {@link Context}-only constructor. 150 */ createInstance(Context context, Class<? extends SettingsQCItem> qcItem)151 static SettingsQCItem createInstance(Context context, 152 Class<? extends SettingsQCItem> qcItem) { 153 try { 154 Constructor<? extends SettingsQCItem> constructor = 155 qcItem.getConstructor(Context.class); 156 Object[] params = new Object[]{context.getApplicationContext()}; 157 return constructor.newInstance(params); 158 } catch (NoSuchMethodException | InstantiationException | IllegalArgumentException 159 | InvocationTargetException | IllegalAccessException e) { 160 throw new IllegalStateException( 161 "Invalid SettingsQCItem class: " + qcItem, e); 162 } 163 } 164 165 /** 166 * Settings QCItems which require background work, such as updating lists should implement a 167 * {@link SettingsQCBackgroundWorker} and return it here. An example of background work is 168 * updating a list of Wifi networks available in the area. 169 * 170 * @return a {@link Class<? extends SettingsQCBackgroundWorker>} to perform background work for 171 * the QCItem. 172 */ getBackgroundWorkerClass()173 Class<? extends SettingsQCBackgroundWorker> getBackgroundWorkerClass() { 174 return null; 175 } 176 } 177