DeviceInfoSettings.java revision d267d377fba9f6685dfd73af51d85c244f1f970f
1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
19d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasaniimport android.app.Activity;
202fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ngimport android.content.ComponentName;
21afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
222fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ngimport android.content.pm.PackageManager;
232fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ngimport android.content.pm.ResolveInfo;
24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Build;
25afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle;
26b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalleyimport android.os.SELinux;
274749fcf762de0e34ac28f927501d42555062c521Dianne Hackbornimport android.os.SystemClock;
28afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.SystemProperties;
29afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.Preference;
30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.PreferenceGroup;
313673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackbornimport android.preference.PreferenceScreen;
322fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ngimport android.provider.Settings;
33afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log;
34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.io.BufferedReader;
36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.io.FileReader;
37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.io.IOException;
382fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ngimport java.util.List;
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.regex.Matcher;
40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.regex.Pattern;
41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
42d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasanipublic class DeviceInfoSettings extends SettingsPreferenceFragment {
43c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani
44362bd107a11e4cb74c53e8058fe0dfaf9baac65fGilles Debunne    private static final String LOG_TAG = "DeviceInfoSettings";
45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
462397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    private static final String FILENAME_PROC_VERSION = "/proc/version";
472397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    private static final String FILENAME_MSV = "/sys/board_properties/soc/msv";
482397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani
49afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_CONTAINER = "container";
50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_TEAM = "team";
51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_CONTRIBUTORS = "contributors";
52afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_TERMS = "terms";
53afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_LICENSE = "license";
54afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_COPYRIGHT = "copyright";
55afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
56a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville    private static final String PROPERTY_URL_SAFETYLEGAL = "ro.url.safetylegal";
57b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley    private static final String PROPERTY_SELINUX_STATUS = "ro.build.selinux";
58c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    private static final String KEY_KERNEL_VERSION = "kernel_version";
59c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    private static final String KEY_BUILD_NUMBER = "build_number";
60c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    private static final String KEY_DEVICE_MODEL = "device_model";
61b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley    private static final String KEY_SELINUX_STATUS = "selinux_status";
62c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    private static final String KEY_BASEBAND_VERSION = "baseband_version";
63c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani    private static final String KEY_FIRMWARE_VERSION = "firmware_version";
643feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu    private static final String KEY_UPDATE_SETTING = "additional_system_update_settings";
652fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
664749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn    long[] mHits = new long[3];
672fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
68afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
69d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani    public void onCreate(Bundle icicle) {
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onCreate(icicle);
712fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
72afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        addPreferencesFromResource(R.xml.device_info_settings);
732fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
74c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        setStringSummary(KEY_FIRMWARE_VERSION, Build.VERSION.RELEASE);
75c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        findPreference(KEY_FIRMWARE_VERSION).setEnabled(true);
76c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        setValueSummary(KEY_BASEBAND_VERSION, "gsm.version.baseband");
772397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        setStringSummary(KEY_DEVICE_MODEL, Build.MODEL + getMsvSuffix());
78c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        setStringSummary(KEY_BUILD_NUMBER, Build.DISPLAY);
79c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        findPreference(KEY_KERNEL_VERSION).setSummary(getFormattedKernelVersion());
80afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
81b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley        if (!SELinux.isSELinuxEnabled()) {
82b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley            String status = getResources().getString(R.string.selinux_status_disabled);
83b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley            setStringSummary(KEY_SELINUX_STATUS, status);
84b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley        } else if (!SELinux.isSELinuxEnforced()) {
85b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley            String status = getResources().getString(R.string.selinux_status_permissive);
86b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley            setStringSummary(KEY_SELINUX_STATUS, status);
87b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley        }
88b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley
89b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley        // Remove selinux information if property is not present
90b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley        removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_SELINUX_STATUS,
91b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley                PROPERTY_SELINUX_STATUS);
92b4e84f34e095ad423b854f66f75aeb36514d49f0Stephen Smalley
93a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville        // Remove Safety information preference if PROPERTY_URL_SAFETYLEGAL is not set
94a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville        removePreferenceIfPropertyMissing(getPreferenceScreen(), "safetylegal",
95a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville                PROPERTY_URL_SAFETYLEGAL);
96a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville
97c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        // Remove Baseband version if wifi-only device
988af88fb8387259e51615709b2d1ea0260f7057fdRobert Greenwalt        if (Utils.isWifiOnly(getActivity())) {
99c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani            getPreferenceScreen().removePreference(findPreference(KEY_BASEBAND_VERSION));
100c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        }
101c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani
102afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /*
103afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * Settings is a generic app and should not contain any device-specific
104afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * info.
105afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         */
106d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        final Activity act = getActivity();
107afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // These are contained in the "container" preference group
108afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        PreferenceGroup parentPreference = (PreferenceGroup) findPreference(KEY_CONTAINER);
109d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_TERMS,
110afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
111d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_LICENSE,
112afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
113d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_COPYRIGHT,
114afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
115d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_TEAM,
116afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
1172fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
118afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // These are contained by the root preference screen
119afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        parentPreference = getPreferenceScreen();
120d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference,
121afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                KEY_SYSTEM_UPDATE_SETTINGS,
122afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
123d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_CONTRIBUTORS,
124afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
1253feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu
1263feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu        // Read platform settings for additional system update setting
1273feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu        boolean isUpdateSettingAvailable =
1283feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu                getResources().getBoolean(R.bool.config_additional_system_update_setting_enable);
1293feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu        if (isUpdateSettingAvailable == false) {
1303feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu            getPreferenceScreen().removePreference(findPreference(KEY_UPDATE_SETTING));
1313feacdf3969800d6c53c6ca6f8ced2f8fc637f7fMeng Hu        }
132afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
1332fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
1343673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn    @Override
1353673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
136c06d4c48a9455d6018f2d793c6b8f211f1131055Amith Yamasani        if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) {
1374749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn            System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
1384749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn            mHits[mHits.length-1] = SystemClock.uptimeMillis();
1394749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn            if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
1404749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                Intent intent = new Intent(Intent.ACTION_MAIN);
1414749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                intent.setClassName("android",
1424749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                        com.android.internal.app.PlatLogoActivity.class.getName());
1434749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                try {
1444749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                    startActivity(intent);
1454749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                } catch (Exception e) {
146362bd107a11e4cb74c53e8058fe0dfaf9baac65fGilles Debunne                    Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
1474749fcf762de0e34ac28f927501d42555062c521Dianne Hackborn                }
1483673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn            }
1493673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn        }
1503673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn        return super.onPreferenceTreeClick(preferenceScreen, preference);
1513673546205ebf1b4c83c212c1032eea38c8adbe7Dianne Hackborn    }
152a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville
153a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville    private void removePreferenceIfPropertyMissing(PreferenceGroup preferenceGroup,
154a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville            String preference, String property ) {
155a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville        if (SystemProperties.get(property).equals(""))
156a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville        {
157a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville            // Property is missing so remove preference from group
158a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville            try {
159a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville                preferenceGroup.removePreference(findPreference(preference));
160a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville            } catch (RuntimeException e) {
161362bd107a11e4cb74c53e8058fe0dfaf9baac65fGilles Debunne                Log.d(LOG_TAG, "Property '" + property + "' missing and no '"
162a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville                        + preference + "' preference");
163a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville            }
164a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville        }
165a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville    }
166a40fb23734cc5d5ac6e69a060cbb488269ad8af3Wink Saville
167afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void setStringSummary(String preference, String value) {
168afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        try {
169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            findPreference(preference).setSummary(value);
170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } catch (RuntimeException e) {
171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            findPreference(preference).setSummary(
172afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                getResources().getString(R.string.device_info_default));
173afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
1752fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng
176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void setValueSummary(String preference, String property) {
177afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        try {
178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            findPreference(preference).setSummary(
1792fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng                    SystemProperties.get(property,
180afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            getResources().getString(R.string.device_info_default)));
181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } catch (RuntimeException e) {
182362bd107a11e4cb74c53e8058fe0dfaf9baac65fGilles Debunne            // No recovery
183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
1862397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    /**
1872397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * Reads a line from the specified file.
1882397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * @param filename the file to read from
1892397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * @return the first line, if any.
1902397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * @throws IOException if the file couldn't be read
1912397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     */
192d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes    private static String readLine(String filename) throws IOException {
1932397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        BufferedReader reader = new BufferedReader(new FileReader(filename), 256);
1942397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        try {
1952397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            return reader.readLine();
1962397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        } finally {
1972397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            reader.close();
1982397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        }
1992397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    }
2002397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani
201d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes    public static String getFormattedKernelVersion() {
202afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        try {
203d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            return formatKernelVersion(readLine(FILENAME_PROC_VERSION));
204afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
2052fc2ba11fedd529340eefc042d3a00ef6f70e7b6Freeman Ng        } catch (IOException e) {
206362bd107a11e4cb74c53e8058fe0dfaf9baac65fGilles Debunne            Log.e(LOG_TAG,
207afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                "IO Exception when getting kernel version for Device Info screen",
208afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                e);
209afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
210afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return "Unavailable";
211afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
212afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
213afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
214d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes    public static String formatKernelVersion(String rawKernelVersion) {
215d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        // Example (see tests for more):
216d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        // Linux version 3.0.31-g6fb96c9 (android-build@xxx.xxx.xxx.xxx.com) \
217d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        //     (gcc version 4.6.x-xxx 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT \
218d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        //     Thu Jun 28 11:02:39 PDT 2012
219d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes
220d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        final String PROC_VERSION_REGEX =
221d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "Linux version (\\S+) " + /* group 1: "3.0.31-g6fb96c9" */
222d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "\\((\\S+?)\\) " +        /* group 2: "x@y.com" (kernel builder) */
223d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "(?:\\(gcc.+? \\)) " +    /* ignore: GCC version information */
224d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "(#\\d+) " +              /* group 3: "#1" */
225d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "(?:.*?)?" +              /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */
226d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            "((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */
227d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes
228d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion);
229d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        if (!m.matches()) {
230d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            Log.e(LOG_TAG, "Regex did not match on /proc/version: " + rawKernelVersion);
231d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            return "Unavailable";
232d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        } else if (m.groupCount() < 4) {
233d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            Log.e(LOG_TAG, "Regex match on /proc/version only returned " + m.groupCount()
234d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes                    + " groups");
235d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            return "Unavailable";
236d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        }
237d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes        return m.group(1) + "\n" +                 // 3.0.31-g6fb96c9
238d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            m.group(2) + " " + m.group(3) + "\n" + // x@y.com #1
239d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes            m.group(4);                            // Thu Jun 28 11:02:39 PDT 2012
240d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes    }
241d267d377fba9f6685dfd73af51d85c244f1f970fElliott Hughes
2422397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    /**
2432397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * Returns " (ENGINEERING)" if the msv file has a zero value, else returns "".
2442397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     * @return a string to append to the model number description.
2452397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani     */
2462397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    private String getMsvSuffix() {
2472397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        // Production devices should have a non-zero value. If we can't read it, assume it's a
2482397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        // production device so that we don't accidentally show that it's an ENGINEERING device.
2492397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        try {
2502397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            String msv = readLine(FILENAME_MSV);
2512397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            // Parse as a hex number. If it evaluates to a zero, then it's an engineering build.
2522397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            if (Long.parseLong(msv, 16) == 0) {
2532397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani                return " (ENGINEERING)";
2542397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            }
2552397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        } catch (IOException ioe) {
2562397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            // Fail quietly, as the file may not exist on some devices.
2572397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        } catch (NumberFormatException nfe) {
2582397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani            // Fail quietly, returning empty string should be sufficient
2592397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        }
2602397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani        return "";
2612397a7391e2ba9434ee89345c1d3a47948d8f226Amith Yamasani    }
262afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
263