Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2010 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 | /* |
| 18 | * This file references fs_error.png, fs_good.png, fs_indeterminate.png, |
| 19 | * and fs_warning.png which are licensed under Creative Commons 3.0 |
| 20 | * by fatcow.com. |
| 21 | * http://www.fatcow.com/free-icons/ |
| 22 | * http://creativecommons.org/licenses/by/3.0/us/ |
| 23 | */ |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 24 | |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 25 | package com.android.cts.verifier.features; |
| 26 | |
Brian Muramatsu | e118187 | 2010-08-20 12:59:39 -0700 | [diff] [blame] | 27 | import com.android.cts.verifier.PassFailButtons; |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 28 | import com.android.cts.verifier.R; |
| 29 | |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 30 | import android.content.pm.FeatureInfo; |
| 31 | import android.content.pm.PackageManager; |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 32 | import android.os.Build; |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 33 | import android.os.Bundle; |
| 34 | import android.view.View; |
| 35 | import android.widget.ImageView; |
| 36 | import android.widget.SimpleAdapter; |
| 37 | import android.widget.TextView; |
| 38 | |
Brian Muramatsu | e118187 | 2010-08-20 12:59:39 -0700 | [diff] [blame] | 39 | import java.util.ArrayList; |
| 40 | import java.util.Collections; |
| 41 | import java.util.Comparator; |
| 42 | import java.util.HashMap; |
Brian Muramatsu | d8d37a4 | 2011-07-07 14:11:26 -0700 | [diff] [blame] | 43 | import java.util.LinkedHashSet; |
| 44 | import java.util.Set; |
Brian Muramatsu | e118187 | 2010-08-20 12:59:39 -0700 | [diff] [blame] | 45 | |
| 46 | public class FeatureSummaryActivity extends PassFailButtons.ListActivity { |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 47 | /** |
| 48 | * Simple storage class for data about an Android feature. |
| 49 | */ |
| 50 | static class Feature { |
| 51 | /** |
| 52 | * The name of the feature. Should be one of the PackageManager.FEATURE* |
| 53 | * constants. |
| 54 | */ |
| 55 | public String name; |
| 56 | |
| 57 | /** |
| 58 | * Indicates whether the field is present on the current device. |
| 59 | */ |
| 60 | public boolean present; |
| 61 | |
| 62 | /** |
| 63 | * Indicates whether the field is required for the current device. |
| 64 | */ |
| 65 | public boolean required; |
| 66 | |
| 67 | /** |
| 68 | * Constructor does not include 'present' because that's a detected |
| 69 | * value, and not set during creation. |
Brian Muramatsu | de69444 | 2011-03-09 14:13:01 -0800 | [diff] [blame] | 70 | * |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 71 | * @param name value for this.name |
| 72 | * @param required value for this.required |
| 73 | */ |
| 74 | public Feature(String name, boolean required) { |
| 75 | this.name = name; |
| 76 | this.required = required; |
| 77 | this.present = false; |
| 78 | } |
Brian Muramatsu | d8d37a4 | 2011-07-07 14:11:26 -0700 | [diff] [blame] | 79 | |
| 80 | @Override |
| 81 | public boolean equals(Object o) { |
| 82 | if (this == o) { |
| 83 | return true; |
| 84 | } else if (o == null || !(o instanceof Feature)) { |
| 85 | return false; |
| 86 | } else { |
| 87 | Feature feature = (Feature) o; |
| 88 | return name.equals(feature.name); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | @Override |
| 93 | public int hashCode() { |
| 94 | return name.hashCode(); |
| 95 | } |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 96 | } |
| 97 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 98 | public static final Feature[] ALL_ECLAIR_FEATURES = { |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 99 | new Feature(PackageManager.FEATURE_CAMERA, true), |
| 100 | new Feature(PackageManager.FEATURE_CAMERA_AUTOFOCUS, false), |
| 101 | new Feature(PackageManager.FEATURE_CAMERA_FLASH, false), |
| 102 | new Feature(PackageManager.FEATURE_LIVE_WALLPAPER, false), |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 103 | new Feature(PackageManager.FEATURE_SENSOR_LIGHT, false), |
| 104 | new Feature(PackageManager.FEATURE_SENSOR_PROXIMITY, false), |
| 105 | new Feature(PackageManager.FEATURE_TELEPHONY, false), |
| 106 | new Feature(PackageManager.FEATURE_TELEPHONY_CDMA, false), |
| 107 | new Feature(PackageManager.FEATURE_TELEPHONY_GSM, false), |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 108 | }; |
| 109 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 110 | public static final Feature[] ALL_FROYO_FEATURES = { |
| 111 | new Feature("android.hardware.bluetooth", true), |
| 112 | new Feature("android.hardware.location", true), |
| 113 | new Feature("android.hardware.location.gps", true), |
| 114 | new Feature("android.hardware.location.network", true), |
| 115 | new Feature("android.hardware.microphone", true), |
| 116 | new Feature("android.hardware.sensor.accelerometer", true), |
| 117 | new Feature("android.hardware.sensor.compass", true), |
| 118 | new Feature("android.hardware.touchscreen", true), |
| 119 | new Feature("android.hardware.touchscreen.multitouch", false), |
| 120 | new Feature("android.hardware.touchscreen.multitouch.distinct", false), |
| 121 | new Feature("android.hardware.wifi", false), |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 122 | }; |
| 123 | |
Reena Lee | f8451ed | 2011-01-27 17:34:17 -0800 | [diff] [blame] | 124 | public static final Feature[] ALL_GINGERBREAD_FEATURES = { |
Brian Muramatsu | d8d37a4 | 2011-07-07 14:11:26 -0700 | [diff] [blame] | 125 | // Required features in prior releases that became optional in GB |
| 126 | new Feature("android.hardware.bluetooth", false), |
| 127 | new Feature("android.hardware.camera", false), |
| 128 | new Feature("android.hardware.location.gps", false), |
| 129 | new Feature("android.hardware.microphone", false), |
| 130 | new Feature("android.hardware.sensor.accelerometer", false), |
| 131 | new Feature("android.hardware.sensor.compass", false), |
| 132 | |
| 133 | // New features in GB |
Reena Lee | f8451ed | 2011-01-27 17:34:17 -0800 | [diff] [blame] | 134 | new Feature("android.hardware.audio.low_latency", false), |
| 135 | new Feature("android.hardware.camera.front", false), |
| 136 | new Feature("android.hardware.nfc", false), |
| 137 | new Feature("android.hardware.sensor.barometer", false), |
| 138 | new Feature("android.hardware.sensor.gyroscope", false), |
| 139 | new Feature("android.hardware.touchscreen.multitouch.jazzhand", false), |
| 140 | new Feature("android.software.sip", false), |
| 141 | new Feature("android.software.sip.voip", false), |
| 142 | }; |
| 143 | |
Brian Muramatsu | fc13382 | 2011-07-27 11:16:29 -0700 | [diff] [blame] | 144 | public static final Feature[] ALL_GINGERBREAD_MR1_FEATURES = { |
| 145 | new Feature("android.hardware.usb.accessory", false), |
| 146 | }; |
| 147 | |
Mac_Wang | 2e9193f | 2011-03-10 14:06:58 +0800 | [diff] [blame] | 148 | public static final Feature[] ALL_HONEYCOMB_FEATURES = { |
Brian Muramatsu | 30e241c | 2011-08-01 16:07:47 -0700 | [diff] [blame] | 149 | // Required features in prior releases that became optional in HC |
| 150 | new Feature("android.hardware.touchscreen", false), |
| 151 | |
Mac_Wang | 2e9193f | 2011-03-10 14:06:58 +0800 | [diff] [blame] | 152 | new Feature("android.hardware.faketouch", true), |
| 153 | }; |
| 154 | |
Brian Muramatsu | 34317ff | 2011-06-06 14:22:49 -0700 | [diff] [blame] | 155 | public static final Feature[] ALL_HONEYCOMB_MR1_FEATURES = { |
Brian Muramatsu | 677fe34 | 2011-07-15 10:46:28 -0700 | [diff] [blame] | 156 | new Feature("android.hardware.usb.host", false), |
Kent Cheng | 5c0b5d8 | 2013-08-07 18:13:26 +0800 | [diff] [blame] | 157 | new Feature("android.hardware.usb.accessory", false), |
Brian Muramatsu | 34317ff | 2011-06-06 14:22:49 -0700 | [diff] [blame] | 158 | }; |
| 159 | |
Brian Muramatsu | 177bac5 | 2011-07-12 18:28:18 -0700 | [diff] [blame] | 160 | public static final Feature[] ALL_HONEYCOMB_MR2_FEATURES = { |
| 161 | new Feature("android.hardware.faketouch.multitouch.distinct", false), |
| 162 | new Feature("android.hardware.faketouch.multitouch.jazzhand", false), |
| 163 | new Feature("android.hardware.screen.landscape", false), |
| 164 | new Feature("android.hardware.screen.portrait", false), |
| 165 | }; |
| 166 | |
Brian Muramatsu | 278962c | 2012-01-19 17:37:38 -0800 | [diff] [blame] | 167 | public static final Feature[] ALL_ICE_CREAM_SANDWICH_FEATURES = { |
| 168 | new Feature(PackageManager.FEATURE_WIFI_DIRECT, false), |
| 169 | }; |
| 170 | |
Leo Liao | 0801e93 | 2013-01-30 10:23:14 +0800 | [diff] [blame] | 171 | public static final Feature[] ALL_JELLY_BEAN_FEATURES = { |
Unsuk Jung | 3a55357 | 2014-11-04 16:59:14 -0800 | [diff] [blame] | 172 | // Required features in prior releases that became optional |
| 173 | new Feature(PackageManager.FEATURE_FAKETOUCH, false), |
| 174 | |
| 175 | //new feature in JB |
Leo Liao | 0801e93 | 2013-01-30 10:23:14 +0800 | [diff] [blame] | 176 | new Feature(PackageManager.FEATURE_TELEVISION, false), |
| 177 | }; |
| 178 | |
Guru Nagarajan | dcaa4d5 | 2013-07-22 13:48:42 -0700 | [diff] [blame] | 179 | public static final Feature[] ALL_JELLY_BEAN_MR2_FEATURES = { |
| 180 | new Feature("android.software.app_widgets", false), |
Guru Nagarajan | d8716c9 | 2013-07-26 15:55:54 -0700 | [diff] [blame] | 181 | new Feature("android.software.input_methods", false), |
Guru Nagarajan | dcaa4d5 | 2013-07-22 13:48:42 -0700 | [diff] [blame] | 182 | new Feature("android.software.home_screen", false), |
| 183 | new Feature("android.hardware.bluetooth_le", false), |
Guru Nagarajan | d8716c9 | 2013-07-26 15:55:54 -0700 | [diff] [blame] | 184 | new Feature("android.hardware.camera.any", false), |
Guru Nagarajan | dcaa4d5 | 2013-07-22 13:48:42 -0700 | [diff] [blame] | 185 | }; |
| 186 | |
Martijn Coenen | 9f342d3 | 2013-10-25 13:59:50 -0700 | [diff] [blame] | 187 | public static final Feature[] ALL_KITKAT_FEATURES = { |
| 188 | new Feature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, false), |
Madan Ankapura | d58c029 | 2013-11-03 23:42:34 -0800 | [diff] [blame] | 189 | new Feature(PackageManager.FEATURE_CONSUMER_IR, false), |
| 190 | new Feature(PackageManager.FEATURE_DEVICE_ADMIN, false), |
| 191 | new Feature(PackageManager.FEATURE_SENSOR_STEP_COUNTER, false), |
| 192 | new Feature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR, false), |
Martijn Coenen | 9f342d3 | 2013-10-25 13:59:50 -0700 | [diff] [blame] | 193 | }; |
| 194 | |
Vinod Krishnan | 20d6725 | 2014-04-30 11:12:01 -0700 | [diff] [blame] | 195 | public static final Feature[] ALL_KITKAT_WATCH_FEATURES = { |
| 196 | new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE, false), |
Unsuk Jung | 3a55357 | 2014-11-04 16:59:14 -0800 | [diff] [blame] | 197 | new Feature(PackageManager.FEATURE_BACKUP, false), |
| 198 | new Feature(PackageManager.FEATURE_PRINTING, false), |
| 199 | new Feature(PackageManager.FEATURE_WATCH, false), |
| 200 | new Feature(PackageManager.FEATURE_WEBVIEW, false), |
| 201 | new Feature(PackageManager.FEATURE_CAMERA_EXTERNAL, false), |
Vinod Krishnan | 20d6725 | 2014-04-30 11:12:01 -0700 | [diff] [blame] | 202 | }; |
| 203 | |
Unsuk Jung | 3a55357 | 2014-11-04 16:59:14 -0800 | [diff] [blame] | 204 | public static final Feature[] ALL_LOLLIPOP_FEATURES = { |
| 205 | // New features in L |
| 206 | new Feature(PackageManager.FEATURE_AUDIO_OUTPUT, false), |
| 207 | new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING, false), |
| 208 | new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR, false), |
| 209 | new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_RAW, false), |
| 210 | new Feature(PackageManager.FEATURE_CAMERA_LEVEL_FULL, false), |
| 211 | new Feature(PackageManager.FEATURE_CONNECTION_SERVICE, false), |
| 212 | new Feature(PackageManager.FEATURE_GAMEPAD, false), |
| 213 | new Feature(PackageManager.FEATURE_LEANBACK, false), |
| 214 | new Feature(PackageManager.FEATURE_LIVE_TV, false), |
| 215 | new Feature(PackageManager.FEATURE_MANAGED_USERS, false), |
| 216 | new Feature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK, false), |
| 217 | new Feature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, false), |
| 218 | new Feature(PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE, false), |
Vinod Krishnan | 9a277c8 | 2014-08-19 14:17:39 -0700 | [diff] [blame] | 219 | new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, false), |
Unsuk Jung | 3a55357 | 2014-11-04 16:59:14 -0800 | [diff] [blame] | 220 | new Feature(PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY, false), |
| 221 | new Feature(PackageManager.FEATURE_VERIFIED_BOOT, false), |
Unsuk Jung | 0f0a2c2 | 2014-11-06 12:57:29 -0800 | [diff] [blame] | 222 | |
Unsuk Jung | c6f34c7 | 2014-12-09 11:51:27 -0800 | [diff] [blame] | 223 | // Features explicitly made optional in L |
Michael Kwan | 9c41815 | 2015-02-10 16:19:21 -0800 | [diff] [blame^] | 224 | new Feature(PackageManager.FEATURE_LOCATION_NETWORK, false), |
Unsuk Jung | c6f34c7 | 2014-12-09 11:51:27 -0800 | [diff] [blame] | 225 | |
Unsuk Jung | 0f0a2c2 | 2014-11-06 12:57:29 -0800 | [diff] [blame] | 226 | // New hidden features in L |
Takayuki Hoshi | fc78f47 | 2014-10-01 01:06:54 +0900 | [diff] [blame] | 227 | new Feature("android.hardware.ethernet", false), |
Unsuk Jung | 0f0a2c2 | 2014-11-06 12:57:29 -0800 | [diff] [blame] | 228 | new Feature("android.hardware.hdmi.cec", false), |
| 229 | new Feature("android.software.leanback_only", false), |
| 230 | new Feature("android.software.voice_recognizers", false), |
Vinod Krishnan | 9a277c8 | 2014-08-19 14:17:39 -0700 | [diff] [blame] | 231 | }; |
| 232 | |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 233 | @Override |
| 234 | public void onCreate(Bundle savedInstanceState) { |
| 235 | super.onCreate(savedInstanceState); |
| 236 | setContentView(R.layout.fs_main); |
Brian Muramatsu | de69444 | 2011-03-09 14:13:01 -0800 | [diff] [blame] | 237 | setPassFailButtonClickListeners(); |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 238 | setInfoResources(R.string.feature_summary, R.string.feature_summary_info, R.layout.fs_info); |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 239 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 240 | // some values used to detect warn-able conditions involving multiple |
| 241 | // features |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 242 | boolean hasWifi = false; |
| 243 | boolean hasTelephony = false; |
Tom Rudick | ef5f6aa | 2014-11-06 17:11:59 -0500 | [diff] [blame] | 244 | boolean hasBluetooth = false; |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 245 | boolean hasIllegalFeature = false; |
| 246 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 247 | // get list of all features device thinks it has, & store in a HashMap |
| 248 | // for fast lookups |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 249 | HashMap<String, String> actualFeatures = new HashMap<String, String>(); |
| 250 | for (FeatureInfo fi : getPackageManager().getSystemAvailableFeatures()) { |
| 251 | actualFeatures.put(fi.name, fi.name); |
| 252 | } |
| 253 | |
| 254 | // data structure that the SimpleAdapter will use to populate ListView |
| 255 | ArrayList<HashMap<String, Object>> listViewData = new ArrayList<HashMap<String, Object>>(); |
| 256 | |
| 257 | // roll over all known features & check whether device reports them |
| 258 | boolean present = false; |
| 259 | int statusIcon; |
Brian Muramatsu | d8d37a4 | 2011-07-07 14:11:26 -0700 | [diff] [blame] | 260 | Set<Feature> features = new LinkedHashSet<Feature>(); |
| 261 | |
| 262 | // add features from latest to last so that the latest requirements are put in the set first |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 263 | int apiVersion = Build.VERSION.SDK_INT; |
Dianne Hackborn | 10e5dc6 | 2014-10-07 20:34:25 -0700 | [diff] [blame] | 264 | if (apiVersion >= Build.VERSION_CODES.LOLLIPOP) { |
Unsuk Jung | 3a55357 | 2014-11-04 16:59:14 -0800 | [diff] [blame] | 265 | Collections.addAll(features, ALL_LOLLIPOP_FEATURES); |
Vinod Krishnan | 9a277c8 | 2014-08-19 14:17:39 -0700 | [diff] [blame] | 266 | } |
Vinod Krishnan | 20d6725 | 2014-04-30 11:12:01 -0700 | [diff] [blame] | 267 | if (apiVersion >= Build.VERSION_CODES.KITKAT_WATCH) { |
| 268 | Collections.addAll(features, ALL_KITKAT_WATCH_FEATURES); |
| 269 | } |
Martijn Coenen | 9f342d3 | 2013-10-25 13:59:50 -0700 | [diff] [blame] | 270 | if (apiVersion >= Build.VERSION_CODES.KITKAT) { |
| 271 | Collections.addAll(features, ALL_KITKAT_FEATURES); |
| 272 | } |
Guru Nagarajan | dcaa4d5 | 2013-07-22 13:48:42 -0700 | [diff] [blame] | 273 | if (apiVersion >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
Guru Nagarajan | 89cd939 | 2013-07-26 15:31:11 -0700 | [diff] [blame] | 274 | Collections.addAll(features, ALL_JELLY_BEAN_MR2_FEATURES); |
Guru Nagarajan | dcaa4d5 | 2013-07-22 13:48:42 -0700 | [diff] [blame] | 275 | } |
Leo Liao | 0801e93 | 2013-01-30 10:23:14 +0800 | [diff] [blame] | 276 | if (apiVersion >= Build.VERSION_CODES.JELLY_BEAN) { |
| 277 | Collections.addAll(features, ALL_JELLY_BEAN_FEATURES); |
| 278 | } |
Brian Muramatsu | 278962c | 2012-01-19 17:37:38 -0800 | [diff] [blame] | 279 | if (apiVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { |
| 280 | Collections.addAll(features, ALL_ICE_CREAM_SANDWICH_FEATURES); |
| 281 | } |
Brian Muramatsu | 177bac5 | 2011-07-12 18:28:18 -0700 | [diff] [blame] | 282 | if (apiVersion >= Build.VERSION_CODES.HONEYCOMB_MR2) { |
| 283 | Collections.addAll(features, ALL_HONEYCOMB_MR2_FEATURES); |
| 284 | } |
Brian Muramatsu | 23c84d9 | 2011-07-12 17:39:28 -0700 | [diff] [blame] | 285 | if (apiVersion >= Build.VERSION_CODES.HONEYCOMB_MR1) { |
| 286 | Collections.addAll(features, ALL_HONEYCOMB_MR1_FEATURES); |
Reena Lee | f8451ed | 2011-01-27 17:34:17 -0800 | [diff] [blame] | 287 | } |
Mac_Wang | 2e9193f | 2011-03-10 14:06:58 +0800 | [diff] [blame] | 288 | if (apiVersion >= Build.VERSION_CODES.HONEYCOMB) { |
| 289 | Collections.addAll(features, ALL_HONEYCOMB_FEATURES); |
| 290 | } |
Brian Muramatsu | fc13382 | 2011-07-27 11:16:29 -0700 | [diff] [blame] | 291 | if (apiVersion >= Build.VERSION_CODES.GINGERBREAD_MR1) { |
| 292 | Collections.addAll(features, ALL_GINGERBREAD_MR1_FEATURES); |
| 293 | } |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 294 | if (apiVersion >= Build.VERSION_CODES.GINGERBREAD) { |
| 295 | Collections.addAll(features, ALL_GINGERBREAD_FEATURES); |
| 296 | } |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 297 | if (apiVersion >= Build.VERSION_CODES.FROYO) { |
| 298 | Collections.addAll(features, ALL_FROYO_FEATURES); |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 299 | } |
Brian Muramatsu | d8d37a4 | 2011-07-07 14:11:26 -0700 | [diff] [blame] | 300 | if (apiVersion >= Build.VERSION_CODES.ECLAIR_MR1) { |
| 301 | Collections.addAll(features, ALL_ECLAIR_FEATURES); |
Brian Muramatsu | 34317ff | 2011-06-06 14:22:49 -0700 | [diff] [blame] | 302 | } |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 303 | for (Feature f : features) { |
| 304 | HashMap<String, Object> row = new HashMap<String, Object>(); |
| 305 | listViewData.add(row); |
| 306 | present = actualFeatures.containsKey(f.name); |
| 307 | if (present) { |
| 308 | // device reports it -- yay! set the happy icon |
| 309 | hasWifi = hasWifi || PackageManager.FEATURE_WIFI.equals(f.name); |
| 310 | hasTelephony = hasTelephony || PackageManager.FEATURE_TELEPHONY.equals(f.name); |
Tom Rudick | ef5f6aa | 2014-11-06 17:11:59 -0500 | [diff] [blame] | 311 | hasBluetooth = hasBluetooth || PackageManager.FEATURE_BLUETOOTH.equals(f.name); |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 312 | statusIcon = R.drawable.fs_good; |
| 313 | actualFeatures.remove(f.name); |
| 314 | } else if (!present && f.required) { |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 315 | // it's required, but device doesn't report it. Boo, set the |
| 316 | // bogus icon |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 317 | statusIcon = R.drawable.fs_error; |
| 318 | } else { |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 319 | // device doesn't report it, but it's not req'd, so can't tell |
| 320 | // if there's a problem |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 321 | statusIcon = R.drawable.fs_indeterminate; |
| 322 | } |
| 323 | row.put("feature", f.name); |
| 324 | row.put("icon", statusIcon); |
| 325 | } |
| 326 | |
| 327 | // now roll over any remaining features (which are non-standard) |
| 328 | for (String feature : actualFeatures.keySet()) { |
| 329 | if (feature == null || "".equals(feature)) |
| 330 | continue; |
| 331 | HashMap<String, Object> row = new HashMap<String, Object>(); |
| 332 | listViewData.add(row); |
| 333 | row.put("feature", feature); |
| 334 | if (feature.startsWith("android")) { // intentionally not "android." |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 335 | // sorry, you're not allowed to squat in the official namespace; |
| 336 | // set bogus icon |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 337 | row.put("icon", R.drawable.fs_error); |
| 338 | hasIllegalFeature = true; |
| 339 | } else { |
| 340 | // non-standard features are okay, but flag them just in case |
| 341 | row.put("icon", R.drawable.fs_warning); |
| 342 | } |
| 343 | } |
| 344 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 345 | // sort the ListView's data to group by icon type, for easier reading by |
| 346 | // humans |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 347 | final HashMap<Integer, Integer> idMap = new HashMap<Integer, Integer>(); |
| 348 | idMap.put(R.drawable.fs_error, 0); |
| 349 | idMap.put(R.drawable.fs_warning, 1); |
| 350 | idMap.put(R.drawable.fs_indeterminate, 2); |
| 351 | idMap.put(R.drawable.fs_good, 3); |
| 352 | Collections.sort(listViewData, new Comparator<HashMap<String, Object>>() { |
| 353 | public int compare(HashMap<String, Object> left, HashMap<String, Object> right) { |
Brian Muramatsu | e118187 | 2010-08-20 12:59:39 -0700 | [diff] [blame] | 354 | int leftId = idMap.get(left.get("icon")); |
| 355 | int rightId = idMap.get(right.get("icon")); |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 356 | if (leftId == rightId) { |
| 357 | return ((String) left.get("feature")).compareTo((String) right.get("feature")); |
| 358 | } |
| 359 | if (leftId < rightId) |
| 360 | return -1; |
| 361 | return 1; |
| 362 | } |
| 363 | }); |
| 364 | |
| 365 | // Set up the SimpleAdapter used to populate the ListView |
| 366 | SimpleAdapter adapter = new SimpleAdapter(this, listViewData, R.layout.fs_row, |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 367 | new String[] { |
| 368 | "feature", "icon" |
| 369 | }, new int[] { |
| 370 | R.id.fs_feature, R.id.fs_icon |
| 371 | }); |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 372 | adapter.setViewBinder(new SimpleAdapter.ViewBinder() { |
| 373 | public boolean setViewValue(View view, Object data, String repr) { |
| 374 | try { |
| 375 | if (view instanceof ImageView) { |
| 376 | ((ImageView) view).setImageResource((Integer) data); |
| 377 | } else if (view instanceof TextView) { |
| 378 | ((TextView) view).setText((String) data); |
| 379 | } else { |
| 380 | return false; |
| 381 | } |
| 382 | return true; |
| 383 | } catch (ClassCastException e) { |
| 384 | return false; |
| 385 | } |
| 386 | } |
| 387 | }); |
| 388 | setListAdapter(adapter); |
| 389 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 390 | // finally, check for our second-order error cases and set warning text |
| 391 | // if necessary |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 392 | StringBuffer sb = new StringBuffer(); |
| 393 | if (hasIllegalFeature) { |
| 394 | sb.append(getResources().getString(R.string.fs_disallowed)).append("\n"); |
| 395 | } |
Tom Rudick | ef5f6aa | 2014-11-06 17:11:59 -0500 | [diff] [blame] | 396 | |
| 397 | if (!hasWifi && !hasTelephony && !hasBluetooth) { |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 398 | sb.append(getResources().getString(R.string.fs_missing_wifi_telephony)).append("\n"); |
| 399 | } |
Tom Rudick | ef5f6aa | 2014-11-06 17:11:59 -0500 | [diff] [blame] | 400 | |
Dan Morrill | 71351d8 | 2010-10-20 15:26:00 -0700 | [diff] [blame] | 401 | String warnings = sb.toString().trim(); |
| 402 | if (warnings == null || "".equals(warnings)) { |
| 403 | ((TextView) (findViewById(R.id.fs_warnings))).setVisibility(View.GONE); |
| 404 | } else { |
| 405 | ((TextView) (findViewById(R.id.fs_warnings))).setText(warnings); |
| 406 | } |
Dan Morrill | 5df275b | 2010-08-11 12:19:19 -0700 | [diff] [blame] | 407 | } |
| 408 | } |