• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.system;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.DialogInterface;
22 import android.content.res.Resources;
23 import android.graphics.Bitmap;
24 import android.graphics.BitmapFactory;
25 import android.graphics.drawable.Drawable;
26 import android.os.Bundle;
27 import android.os.SystemProperties;
28 import android.text.TextUtils;
29 import android.view.Gravity;
30 import android.view.View;
31 import android.widget.ImageView;
32 import android.widget.TextView;
33 
34 import androidx.annotation.VisibleForTesting;
35 
36 import com.android.car.settings.R;
37 
38 import java.util.Locale;
39 
40 /**
41  * Code drop from {@link com.android.settings.RegulatoryInfoDisplayActivity}.
42  *
43  * {@link Activity} that displays regulatory information for the "Regulatory information"
44  * preference item, and when "*#07#" is dialed on the Phone keypad. To enable this feature,
45  * set the "config_show_regulatory_info" boolean to true in a device overlay resource, and in the
46  * same overlay, either add a drawable named "regulatory_info.png" containing a graphical version
47  * of the required regulatory info (If ro.bootloader.hardware.sku property is set use
48  * "regulatory_info_<sku>.png where sku is ro.bootloader.hardware.sku property value in lowercase"),
49  * or add a string resource named "regulatory_info_text" with an HTML version of the required
50  * information (text will be centered in the dialog).
51  */
52 public class RegulatoryInfoDisplayActivity extends Activity implements
53         DialogInterface.OnDismissListener {
54 
55     private static final String DEFAULT_REGULATORY_INFO_FILEPATH =
56             "/data/misc/elabel/regulatory_info.png";
57     private static final String REGULATORY_INFO_FILEPATH_TEMPLATE =
58             "/data/misc/elabel/regulatory_info_%s.png";
59 
60     private final String mRegulatoryInfoResource = "regulatory_info";
61 
62     /**
63      * Display the regulatory info graphic in a dialog window.
64      */
65     @Override
onCreate(Bundle savedInstanceState)66     protected void onCreate(Bundle savedInstanceState) {
67         super.onCreate(savedInstanceState);
68         Resources resources = getResources();
69 
70         if (!resources.getBoolean(R.bool.config_show_regulatory_info)) {
71             finish();   // No regulatory info to display for this device.
72         }
73 
74         AlertDialog.Builder builder = new AlertDialog.Builder(this)
75                 .setTitle(R.string.regulatory_labels)
76                 .setOnDismissListener(this);
77 
78         boolean regulatoryInfoDrawableExists = false;
79 
80         String regulatoryInfoFile = getRegulatoryInfoImageFileName();
81         Bitmap regulatoryInfoBitmap = BitmapFactory.decodeFile(regulatoryInfoFile);
82 
83         if (regulatoryInfoBitmap != null) {
84             regulatoryInfoDrawableExists = true;
85         }
86 
87         int resId = 0;
88         if (!regulatoryInfoDrawableExists) {
89             resId = getImageResourceId();
90         }
91         if (resId != 0) {
92             try {
93                 Drawable d = getDrawable(resId);
94                 // Set to false if the width or height is <= 2.
95                 // (missing PNG can return an empty 2x2 pixel Drawable)
96                 regulatoryInfoDrawableExists = (d.getIntrinsicWidth() > 2
97                         && d.getIntrinsicHeight() > 2);
98             } catch (Resources.NotFoundException ignored) {
99                 regulatoryInfoDrawableExists = false;
100             }
101         }
102 
103         CharSequence regulatoryText = resources.getText(R.string.regulatory_info_text);
104 
105         if (regulatoryInfoDrawableExists) {
106             View view = getLayoutInflater().inflate(R.layout.regulatory_info, null);
107             ImageView image = view.findViewById(R.id.regulatory_info);
108             if (regulatoryInfoBitmap != null) {
109                 image.setImageBitmap(regulatoryInfoBitmap);
110             } else {
111                 image.setImageResource(resId);
112             }
113             builder.setView(view);
114             builder.show();
115         } else if (regulatoryText.length() > 0) {
116             builder.setMessage(regulatoryText);
117             AlertDialog dialog = builder.show();
118             // We have to show the dialog first, or the setGravity() call will throw a NPE.
119             TextView messageText = (TextView) dialog.findViewById(android.R.id.message);
120             messageText.setGravity(Gravity.CENTER);
121         } else {
122             // Neither drawable nor text resource exists, finish activity.
123             finish();
124         }
125     }
126 
getImageResourceId()127     private int getImageResourceId() {
128         // Use regulatory_info by default.
129         int resId = getResources().getIdentifier(
130                 mRegulatoryInfoResource, "drawable", getPackageName());
131 
132         // When hardware sku property exists, use regulatory_info_<sku> resource if valid.
133         String sku = getSku();
134         if (!TextUtils.isEmpty(sku)) {
135             String regulatory_info_res = mRegulatoryInfoResource + "_" + sku.toLowerCase();
136             int id = getResources().getIdentifier(
137                     regulatory_info_res, "drawable", getPackageName());
138             if (id != 0) {
139                 resId = id;
140             }
141         }
142         return resId;
143     }
144 
145     @Override
onDismiss(DialogInterface dialog)146     public void onDismiss(DialogInterface dialog) {
147         finish();
148     }
149 
150     @VisibleForTesting
getSku()151     static String getSku() {
152         return SystemProperties.get("ro.boot.hardware.sku", "");
153     }
154 
155     @VisibleForTesting
getRegulatoryInfoImageFileName()156     static String getRegulatoryInfoImageFileName() {
157         String sku = getSku();
158         if (TextUtils.isEmpty(sku)) {
159             return DEFAULT_REGULATORY_INFO_FILEPATH;
160         } else {
161             return String.format(Locale.US, REGULATORY_INFO_FILEPATH_TEMPLATE, sku.toLowerCase());
162         }
163     }
164 }
165