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.PreferenceXmlParser.METADATA_KEY;
20 import static com.android.car.settings.common.PreferenceXmlParser.METADATA_OCCUPANT_ZONE;
21 import static com.android.car.settings.common.PreferenceXmlParser.PREF_AVAILABILITY_STATUS_WRITE;
22 import static com.android.car.settings.common.PreferenceXmlParser.SUPPORTED_AVAILABILITY_STATUS;
23 
24 import android.annotation.StringRes;
25 import android.annotation.XmlRes;
26 import android.app.PendingIntent;
27 import android.app.admin.DevicePolicyManager;
28 import android.car.CarOccupantZoneManager;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.os.Bundle;
32 import android.text.TextUtils;
33 
34 import com.android.car.settings.CarSettingsApplication;
35 import com.android.car.settings.R;
36 import com.android.car.settings.common.PreferenceXmlParser;
37 import com.android.car.settings.enterprise.ActionDisabledByAdminActivity;
38 
39 import org.xmlpull.v1.XmlPullParserException;
40 
41 import java.io.IOException;
42 import java.util.List;
43 /**
44  * General helper methods for quick controls.
45  */
46 public class QCUtils {
QCUtils()47     private QCUtils() {
48     }
49 
50     /**
51      * See {@link #getActionDisabledDialogIntent(Context, String, int)}.
52      */
getActionDisabledDialogIntent(Context context, String restriction)53     public static PendingIntent getActionDisabledDialogIntent(Context context, String restriction) {
54         return getActionDisabledDialogIntent(context, restriction, /* requestCode= */ 0);
55     }
56 
57     /**
58      * Returns a {@link PendingIntent} for launching a {@link ActionDisabledByAdminActivity} with
59      * the specified restriction and request code.
60      */
getActionDisabledDialogIntent(Context context, String restriction, int requestCode)61     public static PendingIntent getActionDisabledDialogIntent(Context context, String restriction,
62             int requestCode) {
63         Intent intent = new Intent();
64         intent.setClass(context, ActionDisabledByAdminActivity.class);
65         intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction);
66         return PendingIntent.getActivity(context, requestCode, intent,
67                 PendingIntent.FLAG_IMMUTABLE);
68     }
69 
70     /**
71      * Creates a list of {@link PreferenceController}.
72      *
73      * @param context the {@link Context} used to instantiate the controllers.
74      * @param xmlResId the XML resource containing the metadata of the controllers to
75      *         create.
76      * @param prefKeyResId the {@link StringRes} used to find the key for the preference
77      *         managed by this Quick Controls.
78      */
getAvailabilityStatusForZoneFromXml(Context context, @XmlRes int xmlResId, @StringRes int prefKeyResId)79     static String getAvailabilityStatusForZoneFromXml(Context context, @XmlRes int xmlResId,
80             @StringRes int prefKeyResId) {
81         List<Bundle> preferenceMetadata;
82         try {
83             int zoneType = ((CarSettingsApplication) context.getApplicationContext())
84                     .getMyOccupantZoneType();
85             preferenceMetadata = PreferenceXmlParser.extractMetadata(context, xmlResId,
86                     PreferenceXmlParser.MetadataFlag.FLAG_NEED_KEY
87                             | PreferenceXmlParser.getMetadataFlagForOccupantZoneType(zoneType)
88             );
89         } catch (IOException | XmlPullParserException e) {
90             throw new IllegalArgumentException(
91                     "Failed to parse preference XML for getting controllers", e);
92         }
93         String targetPrefKey = context.getString(prefKeyResId);
94         for (Bundle metadata : preferenceMetadata) {
95             String key = metadata.getString(METADATA_KEY);
96             if (TextUtils.isEmpty(key) || !key.equals(targetPrefKey)) {
97                 continue;
98             }
99             String availabilityStatusForZone = metadata.getString(METADATA_OCCUPANT_ZONE);
100             if (!TextUtils.isEmpty(availabilityStatusForZone)
101                     && SUPPORTED_AVAILABILITY_STATUS.contains(availabilityStatusForZone)) {
102                 return availabilityStatusForZone;
103             } else {
104                 break;
105             }
106         }
107         return PREF_AVAILABILITY_STATUS_WRITE;
108     }
109 
110     /** Standardized intent for onclick when qc is disabled for zone */
getDisabledToastBroadcastIntent(Context context)111     public static PendingIntent getDisabledToastBroadcastIntent(Context context) {
112         String message = isPassengerUser(context)
113                 ? context.getString(R.string.restricted_for_passenger)
114                 : context.getString(R.string.restricted_for_driver);
115 
116         Intent intent = new Intent()
117                 .setClass(context, DisabledQCToastBroadcastReceiver.class)
118                 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
119         Bundle bundle = new Bundle();
120         bundle.putString(DisabledQCToastBroadcastReceiver.DISABLED_QC_TOAST_KEY, message);
121         intent.putExtras(bundle);
122 
123         return PendingIntent.getBroadcast(context, /* requestCode= */ 0, intent,
124                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
125     }
126 
127     /** Returns whether the current user is a passenger or not */
isPassengerUser(Context context)128     private static boolean isPassengerUser(Context context) {
129         int zoneType = ((CarSettingsApplication) context.getApplicationContext())
130                 .getMyOccupantZoneType();
131         return zoneType != CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER;
132     }
133 }
134