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