OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / cts / apps / CtsVerifier / src / com / android / cts / verifier / features / FeatureSummaryActivity.java
diff --git a/cts/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/cts/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
new file mode 100644 (file)
index 0000000..4f6e0a3
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file references fs_error.png, fs_good.png, fs_indeterminate.png,
+ * and fs_warning.png which are licensed under Creative Commons 3.0
+ * by fatcow.com.
+ * http://www.fatcow.com/free-icons/
+ * http://creativecommons.org/licenses/by/3.0/us/
+ */
+
+package com.android.cts.verifier.features;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+
+public class FeatureSummaryActivity extends PassFailButtons.ListActivity {
+    /**
+     * Simple storage class for data about an Android feature.
+     */
+    static class Feature {
+        /**
+         * The name of the feature. Should be one of the PackageManager.FEATURE*
+         * constants.
+         */
+        public String name;
+
+        /**
+         * Indicates whether the field is present on the current device.
+         */
+        public boolean present;
+
+        /**
+         * Indicates whether the field is required for the current device.
+         */
+        public boolean required;
+
+        /**
+         * Constructor does not include 'present' because that's a detected
+         * value, and not set during creation.
+         * 
+         * @param name value for this.name
+         * @param required value for this.required
+         */
+        public Feature(String name, boolean required) {
+            this.name = name;
+            this.required = required;
+            this.present = false;
+        }
+    }
+
+    /**
+     * A list of all features added in Eclair (API=7).
+     */
+    public static final Feature[] ALL_ECLAIR_FEATURES = {
+            new Feature(PackageManager.FEATURE_CAMERA, true),
+            new Feature(PackageManager.FEATURE_CAMERA_AUTOFOCUS, false),
+            new Feature(PackageManager.FEATURE_CAMERA_FLASH, false),
+            new Feature(PackageManager.FEATURE_LIVE_WALLPAPER, false),
+            new Feature(PackageManager.FEATURE_SENSOR_LIGHT, false),
+            new Feature(PackageManager.FEATURE_SENSOR_PROXIMITY, false),
+            new Feature(PackageManager.FEATURE_TELEPHONY, false),
+            new Feature(PackageManager.FEATURE_TELEPHONY_CDMA, false),
+            new Feature(PackageManager.FEATURE_TELEPHONY_GSM, false),
+    };
+
+    /**
+     * A list of all features added in FroYo (API=8). Because we want to run on
+     * Eclair devices, we can't use static references to constants added later
+     * than Eclair. We could use Reflection, but we'd still need a list of
+     * string literals (for constant names) anyway, and there's little point in
+     * using Reflection to to look up a constant String value for a constant
+     * String name.
+     */
+    public static final Feature[] ALL_FROYO_FEATURES = {
+            new Feature("android.hardware.bluetooth", true),
+            new Feature("android.hardware.location", true),
+            new Feature("android.hardware.location.gps", true),
+            new Feature("android.hardware.location.network", true),
+            new Feature("android.hardware.microphone", true),
+            new Feature("android.hardware.sensor.accelerometer", true),
+            new Feature("android.hardware.sensor.compass", true),
+            new Feature("android.hardware.touchscreen", true),
+            new Feature("android.hardware.touchscreen.multitouch", false),
+            new Feature("android.hardware.touchscreen.multitouch.distinct", false),
+            new Feature("android.hardware.wifi", false),
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fs_main);
+        setInfoResources(R.string.feature_summary, R.string.feature_summary_info, R.layout.fs_info);
+        setResult(RESULT_CANCELED);
+
+        // some values used to detect warn-able conditions involving multiple
+        // features
+        boolean hasWifi = false;
+        boolean hasTelephony = false;
+        boolean hasIllegalFeature = false;
+
+        // get list of all features device thinks it has, & store in a HashMap
+        // for fast lookups
+        HashMap<String, String> actualFeatures = new HashMap<String, String>();
+        for (FeatureInfo fi : getPackageManager().getSystemAvailableFeatures()) {
+            actualFeatures.put(fi.name, fi.name);
+        }
+
+        // data structure that the SimpleAdapter will use to populate ListView
+        ArrayList<HashMap<String, Object>> listViewData = new ArrayList<HashMap<String, Object>>();
+
+        // roll over all known features & check whether device reports them
+        boolean present = false;
+        int statusIcon;
+        ArrayList<Feature> features = new ArrayList<Feature>();
+        int apiVersion = Build.VERSION.SDK_INT;
+        if (apiVersion >= Build.VERSION_CODES.ECLAIR_MR1) {
+            Collections.addAll(features, ALL_ECLAIR_FEATURES);
+        }
+        if (apiVersion >= Build.VERSION_CODES.FROYO) {
+            Collections.addAll(features, ALL_FROYO_FEATURES);
+        }
+        for (Feature f : features) {
+            HashMap<String, Object> row = new HashMap<String, Object>();
+            listViewData.add(row);
+            present = actualFeatures.containsKey(f.name);
+            if (present) {
+                // device reports it -- yay! set the happy icon
+                hasWifi = hasWifi || PackageManager.FEATURE_WIFI.equals(f.name);
+                hasTelephony = hasTelephony || PackageManager.FEATURE_TELEPHONY.equals(f.name);
+                statusIcon = R.drawable.fs_good;
+                actualFeatures.remove(f.name);
+            } else if (!present && f.required) {
+                // it's required, but device doesn't report it. Boo, set the
+                // bogus icon
+                statusIcon = R.drawable.fs_error;
+            } else {
+                // device doesn't report it, but it's not req'd, so can't tell
+                // if there's a problem
+                statusIcon = R.drawable.fs_indeterminate;
+            }
+            row.put("feature", f.name);
+            row.put("icon", statusIcon);
+        }
+
+        // now roll over any remaining features (which are non-standard)
+        for (String feature : actualFeatures.keySet()) {
+            if (feature == null || "".equals(feature))
+                continue;
+            HashMap<String, Object> row = new HashMap<String, Object>();
+            listViewData.add(row);
+            row.put("feature", feature);
+            if (feature.startsWith("android")) { // intentionally not "android."
+                // sorry, you're not allowed to squat in the official namespace;
+                // set bogus icon
+                row.put("icon", R.drawable.fs_error);
+                hasIllegalFeature = true;
+            } else {
+                // non-standard features are okay, but flag them just in case
+                row.put("icon", R.drawable.fs_warning);
+            }
+        }
+
+        // sort the ListView's data to group by icon type, for easier reading by
+        // humans
+        final HashMap<Integer, Integer> idMap = new HashMap<Integer, Integer>();
+        idMap.put(R.drawable.fs_error, 0);
+        idMap.put(R.drawable.fs_warning, 1);
+        idMap.put(R.drawable.fs_indeterminate, 2);
+        idMap.put(R.drawable.fs_good, 3);
+        Collections.sort(listViewData, new Comparator<HashMap<String, Object>>() {
+            public int compare(HashMap<String, Object> left, HashMap<String, Object> right) {
+                int leftId = idMap.get(left.get("icon"));
+                int rightId = idMap.get(right.get("icon"));
+                if (leftId == rightId) {
+                    return ((String) left.get("feature")).compareTo((String) right.get("feature"));
+                }
+                if (leftId < rightId)
+                    return -1;
+                return 1;
+            }
+        });
+
+        // Set up the SimpleAdapter used to populate the ListView
+        SimpleAdapter adapter = new SimpleAdapter(this, listViewData, R.layout.fs_row,
+                new String[] {
+                        "feature", "icon"
+                }, new int[] {
+                        R.id.fs_feature, R.id.fs_icon
+                });
+        adapter.setViewBinder(new SimpleAdapter.ViewBinder() {
+            public boolean setViewValue(View view, Object data, String repr) {
+                try {
+                    if (view instanceof ImageView) {
+                        ((ImageView) view).setImageResource((Integer) data);
+                    } else if (view instanceof TextView) {
+                        ((TextView) view).setText((String) data);
+                    } else {
+                        return false;
+                    }
+                    return true;
+                } catch (ClassCastException e) {
+                    return false;
+                }
+            }
+        });
+        setListAdapter(adapter);
+
+        // finally, check for our second-order error cases and set warning text
+        // if necessary
+        StringBuffer sb = new StringBuffer();
+        if (hasIllegalFeature) {
+            sb.append(getResources().getString(R.string.fs_disallowed)).append("\n");
+        }
+        if (!hasWifi && !hasTelephony) {
+            sb.append(getResources().getString(R.string.fs_missing_wifi_telephony)).append("\n");
+        }
+        String warnings = sb.toString().trim();
+        if (warnings == null || "".equals(warnings)) {
+            ((TextView) (findViewById(R.id.fs_warnings))).setVisibility(View.GONE);
+        } else {
+            ((TextView) (findViewById(R.id.fs_warnings))).setText(warnings);
+        }
+    }
+}