Merge "Split ActionBar in Settings"
diff --git a/Android.mk b/Android.mk
index b171dbd..c08be7f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,6 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+LOCAL_JAVA_LIBRARIES := bouncycastle
 LOCAL_STATIC_JAVA_LIBRARIES := guava
 
 LOCAL_MODULE_TAGS := optional
diff --git a/res/layout/trusted_credential.xml b/res/layout/trusted_credential.xml
new file mode 100644
index 0000000..9955a79
--- /dev/null
+++ b/res/layout/trusted_credential.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:paddingRight="?android:attr/scrollbarSize"
+    android:background="?android:attr/selectableItemBackground"
+    android:padding="15dip"
+    >
+    <TextView
+        android:id="@+id/trusted_credential_subject"
+        android:layout_width="0px"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+    />
+    <!-- checkbox is invisible and not gone so that the height is consistent between tabs -->
+    <CheckBox
+        android:id="@+id/trusted_credential_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="invisible"
+        android:clickable="false"
+        android:focusable="false"
+        android:layout_weight="0"
+    />
+</LinearLayout>
diff --git a/res/layout/trusted_credential_details.xml b/res/layout/trusted_credential_details.xml
new file mode 100644
index 0000000..c18d933
--- /dev/null
+++ b/res/layout/trusted_credential_details.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    <FrameLayout
+        android:id="@+id/cert_details"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        />
+    <Button
+        android:id="@+id/cert_remove_button"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="right"
+        android:layout_margin="6dip"
+        />
+</LinearLayout>
diff --git a/res/layout/trusted_credentials.xml b/res/layout/trusted_credentials.xml
new file mode 100644
index 0000000..06ce44b
--- /dev/null
+++ b/res/layout/trusted_credentials.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<TabHost
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:padding="5dp"
+        >
+        <TabWidget
+            android:id="@android:id/tabs"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+         />
+        <FrameLayout
+            android:id="@android:id/tabcontent"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:padding="5dp"
+            >
+            <FrameLayout
+                android:id="@+id/system_tab"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                >
+                <ProgressBar
+                    android:id="@+id/system_progress"
+                    style="?android:attr/progressBarStyleLarge"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:visibility="gone"
+                />
+                <ListView
+                    android:id="@+id/system_list"
+                    android:layout_width="fill_parent"
+                    android:layout_height="fill_parent"
+                    android:visibility="gone"
+                    >
+                </ListView>
+            </FrameLayout>
+            <FrameLayout
+                android:id="@+id/user_tab"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                >
+                <ProgressBar
+                    android:id="@+id/user_progress"
+                    style="?android:attr/progressBarStyleLarge"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:visibility="gone"
+                />
+                <ListView
+                    android:id="@+id/user_list"
+                    android:layout_width="fill_parent"
+                    android:layout_height="fill_parent"
+                    android:visibility="gone"
+                    >
+                </ListView>
+            </FrameLayout>
+        </FrameLayout>
+    </LinearLayout>
+</TabHost>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a2ec8b6..137b171 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1082,6 +1082,10 @@
     <string name="wifi_notify_open_networks">Network notification</string>
     <!-- Checkbox summary for option to notify user when open networks are nearby -->
     <string name="wifi_notify_open_networks_summary">Notify me when an open network is available</string>
+    <!-- Checkbox title for option to toggle wifi watchdog service -->
+    <string name="wifi_enable_watchdog_service">Wi-Fi Connectivity Checks</string>
+    <!-- Checkbox summary for option to toggle wifi watchdog service -->
+    <string name="wifi_enable_watchdog_service_summary">Detect and manage potential network connectivity problems</string>
     <!-- Setting title for setting the wifi sleep policy -->
     <string name="wifi_setting_sleep_policy_title">Wi-Fi disconnect policy</string>
     <!-- Setting summary for setting the wifi sleep policy -->
@@ -2548,7 +2552,7 @@
     <string name="builtin_keyboard_settings_summary">Physical keyboard settings</string>
 
     <!-- Development Settings.  the title for the item to take the user to Development settings.  Development settings are settings meant for application developers.  -->
-    <string name="development_settings_title">Development</string>
+    <string name="development_settings_title">Developer options</string>
     <!-- Development Settings summary.  The summary of the item to take the user to Development settings.  Development settings are settings meant for application developers. -->
     <string name="development_settings_summary">Set options for application development</string>
     <!-- Setting checkbox title for Whether to enable USB debugging support on the phone. -->
@@ -3091,6 +3095,10 @@
     <string name="credentials_reset">Clear credentials</string>
     <!-- Summary of preference to reset credential storage [CHAR LIMIT=NONE] -->
     <string name="credentials_reset_summary">Remove all certificates</string>
+    <!-- Title of preference to display trusted credentials (aka CA certificates) [CHAR LIMIT=30] -->
+    <string name="trusted_credentials">Trusted credentials</string>
+    <!-- Summary of preference to display trusted credentials (aka CA certificates) [CHAR LIMIT=NONE] -->
+    <string name="trusted_credentials_summary">Display trusted CA certificates</string>
 
     <!-- Title of dialog to enable credential storage [CHAR LIMIT=30] -->
     <string name="credentials_unlock">Enter password</string>
@@ -3533,4 +3541,22 @@
     <string name="vpn_menu_edit">Edit network</string>
     <!-- Menu item to delete a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_menu_delete">Delete network</string>
+
+    <!-- Tab label for built-in system CA certificates. -->
+    <string name="trusted_credentials_system_tab">System</string>
+    <!-- Tab label for user added CA certificates. -->
+    <string name="trusted_credentials_user_tab">User</string>
+    <!-- Button label for disabling a system CA certificate. -->
+    <string name="trusted_credentials_disable_label">Disable</string>
+    <!-- Button label for enabling a system CA certificate. -->
+    <string name="trusted_credentials_enable_label">Enable</string>
+    <!-- Button label for removing a user CA certificate. -->
+    <string name="trusted_credentials_remove_label">Remove</string>
+    <!-- Alert dialog confirmation when enabling a system CA certificate. -->
+    <string name="trusted_credentials_enable_confirmation">Enable the system CA certificate?</string>
+    <!-- Alert dialog confirmation when disabling a system CA certificate. -->
+    <string name="trusted_credentials_disable_confirmation">Disable the system CA certificate?</string>
+    <!-- Alert dialog confirmation when removing a user CA certificate. -->
+    <string name="trusted_credentials_remove_confirmation">Permanently remove the user CA certificate?</string>
+
 </resources>
diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml
index 492c9d1..4dfc718 100644
--- a/res/xml/device_info_settings.xml
+++ b/res/xml/device_info_settings.xml
@@ -23,7 +23,7 @@
                 android:summary="@string/system_update_settings_list_item_summary">
             <intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS" />
         </PreferenceScreen>
-        
+
         <!-- Device status - launches activity -->
         <PreferenceScreen android:key="status_info"
                 android:title="@string/device_status" 
@@ -32,13 +32,6 @@
                     android:targetPackage="com.android.settings"
                     android:targetClass="com.android.settings.deviceinfo.Status" />
         </PreferenceScreen>
-        
-        <PreferenceScreen
-                android:key="power_usage"
-                android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
-                android:title="@string/power_usage_summary_title"
-                android:summary="@string/power_usage_summary">
-        </PreferenceScreen>
 
         <!-- Legal Information -->
         <PreferenceScreen
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index e996f70..3a88d0b 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -56,6 +56,11 @@
 
     <PreferenceCategory android:title="@string/credentials_title"
             android:persistent="false">
+        <Preference android:title="@string/trusted_credentials"
+                android:summary="@string/trusted_credentials_summary"
+                android:persistent="false"
+                android:fragment="com.android.settings.TrustedCredentials"/>
+
         <Preference android:title="@string/credentials_install"
                 android:summary="@string/credentials_install_summary"
                 android:persistent="false">
diff --git a/res/xml/wifi_advanced_settings.xml b/res/xml/wifi_advanced_settings.xml
index 1444de1..d7344b1 100644
--- a/res/xml/wifi_advanced_settings.xml
+++ b/res/xml/wifi_advanced_settings.xml
@@ -24,6 +24,13 @@
             android:summary="@string/wifi_notify_open_networks_summary"
             android:persistent="false" />
 
+    <!-- android:dependency="enable_wifi" -->
+    <CheckBoxPreference
+            android:key="wifi_enable_watchdog_service"
+            android:title="@string/wifi_enable_watchdog_service"
+            android:summary="@string/wifi_enable_watchdog_service_summary"
+            android:persistent="false" />
+
     <ListPreference
             android:key="sleep_policy"
             android:title="@string/wifi_setting_sleep_policy_title"
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/CryptKeeperSettings.java
index a9002fa..41a4be5 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/CryptKeeperSettings.java
@@ -63,8 +63,14 @@
             if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                 int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+                int invalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
+
                 boolean levelOk = level >= MIN_BATTERY_LEVEL;
-                boolean pluggedOk = plugged == BatteryManager.BATTERY_PLUGGED_AC;
+                boolean pluggedOk =
+                    (plugged == BatteryManager.BATTERY_PLUGGED_AC ||
+                     plugged == BatteryManager.BATTERY_PLUGGED_USB) &&
+                     invalidCharger == 0;
+
                 // Update UI elements based on power/battery status
                 mInitiateButton.setEnabled(levelOk && pluggedOk);
                 mPowerWarning.setVisibility(pluggedOk ? View.GONE : View.VISIBLE );
diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java
index c3fe955..76f5a8e 100644
--- a/src/com/android/settings/DeviceInfoSettings.java
+++ b/src/com/android/settings/DeviceInfoSettings.java
@@ -40,7 +40,7 @@
 
 public class DeviceInfoSettings extends SettingsPreferenceFragment {
 
-    private static final String TAG = "DeviceInfoSettings";
+    private static final String LOG_TAG = "DeviceInfoSettings";
 
     private static final String KEY_CONTAINER = "container";
     private static final String KEY_TEAM = "team";
@@ -128,6 +128,7 @@
                 try {
                     startActivity(intent);
                 } catch (Exception e) {
+                    Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
                 }
             }
         }
@@ -142,7 +143,7 @@
             try {
                 preferenceGroup.removePreference(findPreference(preference));
             } catch (RuntimeException e) {
-                Log.d(TAG, "Property '" + property + "' missing and no '"
+                Log.d(LOG_TAG, "Property '" + property + "' missing and no '"
                         + preference + "' preference");
             }
         }
@@ -163,7 +164,7 @@
                     SystemProperties.get(property,
                             getResources().getString(R.string.device_info_default)));
         } catch (RuntimeException e) {
-
+            // No recovery
         }
     }
 
@@ -192,10 +193,10 @@
             Matcher m = p.matcher(procVersionStr);
 
             if (!m.matches()) {
-                Log.e(TAG, "Regex did not match on /proc/version: " + procVersionStr);
+                Log.e(LOG_TAG, "Regex did not match on /proc/version: " + procVersionStr);
                 return "Unavailable";
             } else if (m.groupCount() < 4) {
-                Log.e(TAG, "Regex match on /proc/version only returned " + m.groupCount()
+                Log.e(LOG_TAG, "Regex match on /proc/version only returned " + m.groupCount()
                         + " groups");
                 return "Unavailable";
             } else {
@@ -204,7 +205,7 @@
                         .append(m.group(4))).toString();
             }
         } catch (IOException e) {
-            Log.e(TAG,
+            Log.e(LOG_TAG,
                 "IO Exception when getting kernel version for Device Info screen",
                 e);
 
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 0010779..c63d061 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -216,7 +216,9 @@
     public Intent getIntent() {
         Intent superIntent = super.getIntent();
         String startingFragment = getStartingFragmentClass(superIntent);
-        if (startingFragment != null && !isMultiPane()) {
+        // This is called from super.onCreate, isMultiPane() is not yet reliable
+        // Do not use onIsHidingHeaders either, which relies itself on this method
+        if (startingFragment != null && !onIsMultiPane()) {
             Intent modIntent = new Intent(superIntent);
             modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
             Bundle args = superIntent.getExtras();
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
index f7945d8..d76f08f 100644
--- a/src/com/android/settings/TextToSpeechSettings.java
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -26,15 +26,12 @@
 import android.app.AlertDialog;
 import android.content.ActivityNotFoundException;
 import android.content.ContentResolver;
-import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceGroup;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.speech.tts.TextToSpeech;
@@ -695,13 +692,16 @@
         mTts = new TextToSpeech(getActivity().getApplicationContext(), this, engine);
         mEnableDemo = false;
         mVoicesMissing = false;
-        updateWidgetState();
-        checkVoiceData();
 
-        // Finally, persist this value to settings.
+        // Persist this value to settings and update the UI before we check
+        // voice data because if the TTS class connected without any exception, "engine"
+        // will be the default engine irrespective of whether the voice check
+        // passes or not.
         Settings.Secure.putString(getContentResolver(), TTS_DEFAULT_SYNTH, engine);
-        // .. and update the UI.
         mDefaultSynthPref.setValue(engine);
+        updateWidgetState();
+
+        checkVoiceData();
 
         Log.v(TAG, "The default synth is now: " + engine);
     }
diff --git a/src/com/android/settings/TrustedCredentials.java b/src/com/android/settings/TrustedCredentials.java
new file mode 100644
index 0000000..987d2dc
--- /dev/null
+++ b/src/com/android/settings/TrustedCredentials.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.settings;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.content.DialogInterface;
+import android.net.http.SslCertificate;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.security.IKeyChainService;
+import android.security.KeyChain;
+import android.security.KeyChain.KeyChainConnection;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.FrameLayout;
+import android.widget.ListView;
+import android.widget.TabHost;
+import android.widget.TextView;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
+
+public class TrustedCredentials extends Fragment {
+
+    private static final String TAG = "TrustedCredentials";
+
+    private enum Tab {
+        SYSTEM("system",
+               R.string.trusted_credentials_system_tab,
+               R.id.system_tab,
+               R.id.system_progress,
+               R.id.system_list,
+               true),
+        USER("user",
+             R.string.trusted_credentials_user_tab,
+             R.id.user_tab,
+             R.id.user_progress,
+             R.id.user_list,
+             false);
+
+        private final String mTag;
+        private final int mLabel;
+        private final int mView;
+        private final int mProgress;
+        private final int mList;
+        private final boolean mCheckbox;
+        private Tab(String tag, int label, int view, int progress, int list, boolean checkbox) {
+            mTag = tag;
+            mLabel = label;
+            mView = view;
+            mProgress = progress;
+            mList = list;
+            mCheckbox = checkbox;
+        }
+        private Set<String> getAliases(TrustedCertificateStore store) {
+            switch (this) {
+                case SYSTEM:
+                    return store.allSystemAliases();
+                case USER:
+                    return store.userAliases();
+            }
+            throw new AssertionError();
+        }
+        private boolean deleted(TrustedCertificateStore store, String alias) {
+            switch (this) {
+                case SYSTEM:
+                    return !store.containsAlias(alias);
+                case USER:
+                    return false;
+            }
+            throw new AssertionError();
+        }
+        private int getButtonLabel(CertHolder certHolder) {
+            switch (this) {
+                case SYSTEM:
+                    if (certHolder.mDeleted) {
+                        return R.string.trusted_credentials_enable_label;
+                    }
+                    return R.string.trusted_credentials_disable_label;
+                case USER:
+                    return R.string.trusted_credentials_remove_label;
+            }
+            throw new AssertionError();
+        }
+        private int getButtonConfirmation(CertHolder certHolder) {
+            switch (this) {
+                case SYSTEM:
+                    if (certHolder.mDeleted) {
+                        return R.string.trusted_credentials_enable_confirmation;
+                    }
+                    return R.string.trusted_credentials_disable_confirmation;
+                case USER:
+                    return R.string.trusted_credentials_remove_confirmation;
+            }
+            throw new AssertionError();
+        }
+        private void postOperationUpdate(boolean ok, CertHolder certHolder) {
+            if (ok) {
+                if (certHolder.mTab.mCheckbox) {
+                    certHolder.mDeleted = !certHolder.mDeleted;
+                } else {
+                    certHolder.mAdapter.mCertHolders.remove(certHolder);
+                }
+                certHolder.mAdapter.notifyDataSetChanged();
+            } else {
+                // bail, reload to reset to known state
+                certHolder.mAdapter.load();
+            }
+        }
+    }
+
+    // be careful not to use this on the UI thread since it is does file operations
+    private final TrustedCertificateStore mStore = new TrustedCertificateStore();
+
+    private TabHost mTabHost;
+
+    @Override public View onCreateView(
+            LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+        mTabHost = (TabHost) inflater.inflate(R.layout.trusted_credentials, parent, false);
+        mTabHost.setup();
+        addTab(Tab.SYSTEM);
+        // TODO add Install button on Tab.USER to go to CertInstaller like KeyChainActivity
+        addTab(Tab.USER);
+        return mTabHost;
+    }
+
+    private void addTab(Tab tab) {
+        TabHost.TabSpec systemSpec = mTabHost.newTabSpec(tab.mTag)
+                .setIndicator(getActivity().getString(tab.mLabel))
+                .setContent(tab.mView);
+        mTabHost.addTab(systemSpec);
+
+        ListView lv = (ListView) mTabHost.findViewById(tab.mList);
+        final TrustedCertificateAdapter adapter = new TrustedCertificateAdapter(tab);
+        lv.setAdapter(adapter);
+        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
+                showCertDialog(adapter.getItem(pos));
+            }
+        });
+    }
+
+    private class TrustedCertificateAdapter extends BaseAdapter {
+        private final List<CertHolder> mCertHolders = new ArrayList<CertHolder>();
+        private final Tab mTab;
+        private TrustedCertificateAdapter(Tab tab) {
+            mTab = tab;
+            load();
+        }
+        private void load() {
+            new AliasLoader().execute();
+        }
+        @Override public int getCount() {
+            return mCertHolders.size();
+        }
+        @Override public CertHolder getItem(int position) {
+            return mCertHolders.get(position);
+        }
+        @Override public long getItemId(int position) {
+            return position;
+        }
+        @Override public View getView(int position, View view, ViewGroup parent) {
+            ViewHolder holder;
+            if (view == null) {
+                LayoutInflater inflater = LayoutInflater.from(getActivity());
+                view = inflater.inflate(R.layout.trusted_credential, parent, false);
+                holder = new ViewHolder();
+                holder.mSubjectView = (TextView)view.findViewById(R.id.trusted_credential_subject);
+                holder.mCheckBox = (CheckBox) view.findViewById(R.id.trusted_credential_status);
+                view.setTag(holder);
+            } else {
+                holder = (ViewHolder) view.getTag();
+            }
+            CertHolder certHolder = mCertHolders.get(position);
+            holder.mSubjectView.setText(certHolder.mSubject);
+            if (mTab.mCheckbox) {
+                holder.mCheckBox.setChecked(!certHolder.mDeleted);
+                holder.mCheckBox.setVisibility(View.VISIBLE);
+            }
+            return view;
+        };
+
+        private class AliasLoader extends AsyncTask<Void, Void, List<CertHolder>> {
+            @Override protected void onPreExecute() {
+                View content = mTabHost.getTabContentView();
+                content.findViewById(mTab.mProgress).setVisibility(View.VISIBLE);
+                content.findViewById(mTab.mList).setVisibility(View.GONE);
+            }
+            @Override protected List<CertHolder> doInBackground(Void... params) {
+                Set<String> aliases = mTab.getAliases(mStore);
+                List<CertHolder> certHolders = new ArrayList<CertHolder>(aliases.size());
+                for (String alias : aliases) {
+                    X509Certificate cert = (X509Certificate) mStore.getCertificate(alias, true);
+                    certHolders.add(new CertHolder(mStore,
+                                                   TrustedCertificateAdapter.this,
+                                                   mTab,
+                                                   alias,
+                                                   cert));
+                }
+                Collections.sort(certHolders);
+                return certHolders;
+            }
+            @Override protected void onPostExecute(List<CertHolder> certHolders) {
+                mCertHolders.clear();
+                mCertHolders.addAll(certHolders);
+                notifyDataSetChanged();
+                View content = mTabHost.getTabContentView();
+                content.findViewById(mTab.mProgress).setVisibility(View.GONE);
+                content.findViewById(mTab.mList).setVisibility(View.VISIBLE);
+            }
+        }
+    }
+
+    private static class CertHolder implements Comparable<CertHolder> {
+        private final TrustedCertificateStore mStore;
+        private final TrustedCertificateAdapter mAdapter;
+        private final Tab mTab;
+        private final String mAlias;
+        private final X509Certificate mX509Cert;
+
+        private final SslCertificate mSslCert;
+        private final String mSubject;
+        private boolean mDeleted;
+
+        private CertHolder(TrustedCertificateStore store,
+                           TrustedCertificateAdapter adapter,
+                           Tab tab,
+                           String alias,
+                           X509Certificate x509Cert) {
+            mStore = store;
+            mAdapter = adapter;
+            mTab = tab;
+            mAlias = alias;
+            mX509Cert = x509Cert;
+
+            mSslCert = new SslCertificate(x509Cert);
+
+            String cn = mSslCert.getIssuedTo().getCName();
+            String o = mSslCert.getIssuedTo().getOName();
+            String ou = mSslCert.getIssuedTo().getUName();
+            StringBuilder sb = new StringBuilder();
+            if (!cn.isEmpty()) {
+                sb.append("CN=" + cn);
+            }
+            if (!o.isEmpty()) {
+                if (sb.length() != 0) {
+                    sb.append(", ");
+                }
+                sb.append("O=" + o);
+            }
+            if (!ou.isEmpty()) {
+                if (sb.length() != 0) {
+                    sb.append(", ");
+                }
+                sb.append("OU=" + ou);
+            }
+            if (sb.length() != 0) {
+                mSubject = sb.toString();
+            } else {
+                mSubject = mSslCert.getIssuedTo().getDName();
+            }
+
+            mDeleted = mTab.deleted(mStore, mAlias);
+        }
+        @Override public int compareTo(CertHolder o) {
+            return this.mSubject.compareTo(o.mSubject);
+        }
+        @Override public boolean equals(Object o) {
+            if (!(o instanceof CertHolder)) {
+                return false;
+            }
+            CertHolder other = (CertHolder) o;
+            return mAlias.equals(other.mAlias);
+        }
+        @Override public int hashCode() {
+            return mAlias.hashCode();
+        }
+    }
+
+    private static class ViewHolder {
+        private TextView mSubjectView;
+        private CheckBox mCheckBox;
+    }
+
+    private void showCertDialog(final CertHolder certHolder) {
+        View view = View.inflate(getActivity(), R.layout.trusted_credential_details, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(com.android.internal.R.string.ssl_certificate);
+        builder.setView(view);
+        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+            @Override public void onClick(DialogInterface dialog, int id) {
+                dialog.dismiss();
+            }
+        });
+        final Dialog certDialog = builder.create();
+
+        FrameLayout details = (FrameLayout) view.findViewById(R.id.cert_details);
+        details.addView(certHolder.mSslCert.inflateCertificateView(getActivity()));
+
+        Button removeButton = (Button) view.findViewById(R.id.cert_remove_button);
+        removeButton.setText(certHolder.mTab.getButtonLabel(certHolder));
+        removeButton.setOnClickListener(new View.OnClickListener() {
+            @Override public void onClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setMessage(certHolder.mTab.getButtonConfirmation(certHolder));
+                builder.setPositiveButton(
+                        android.R.string.yes, new DialogInterface.OnClickListener() {
+                    @Override public void onClick(DialogInterface dialog, int id) {
+                        new AliasOperation(certHolder).execute();
+                        dialog.dismiss();
+                        certDialog.dismiss();
+                    }
+                });
+                builder.setNegativeButton(
+                        android.R.string.no, new DialogInterface.OnClickListener() {
+                    @Override public void onClick(DialogInterface dialog, int id) {
+                        dialog.cancel();
+                    }
+                });
+                AlertDialog alert = builder.create();
+                alert.show();
+            }
+        });
+
+        certDialog.show();
+    }
+
+    private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
+        private final CertHolder mCertHolder;
+        private AliasOperation(CertHolder certHolder) {
+            mCertHolder = certHolder;
+        }
+        @Override protected Boolean doInBackground(Void... params) {
+            try {
+                KeyChainConnection keyChainConnection = KeyChain.bind(getActivity());
+                IKeyChainService service = keyChainConnection.getService();
+                try {
+                    if (mCertHolder.mDeleted) {
+                        byte[] bytes = mCertHolder.mX509Cert.getEncoded();
+                        service.installCaCertificate(bytes);
+                        return true;
+                    } else {
+                        return service.deleteCaCertificate(mCertHolder.mAlias);
+                    }
+                } finally {
+                    keyChainConnection.close();
+                }
+            } catch (CertificateEncodingException e) {
+                return false;
+            } catch (IllegalStateException e) {
+                // used by installCaCertificate to report errors
+                return false;
+            } catch (RemoteException e) {
+                return false;
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                return false;
+            }
+        }
+        @Override protected void onPostExecute(Boolean ok) {
+            mCertHolder.mTab.postOperationUpdate(ok, mCertHolder);
+        }
+    }
+}
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index caf7aef..1c02f74 100644
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -282,7 +282,7 @@
                         intent.setPackage(mAppEntry.info.packageName);
                         List<ResolveInfo> homes = mPm.queryIntentActivities(intent, 0);
                         if ((homes != null && homes.size() > 0) ||
-                                (mPackageInfo != null &&
+                                (mPackageInfo != null && mPackageInfo.signatures != null &&
                                         sys.signatures[0].equals(mPackageInfo.signatures[0]))) {
                             // Disable button for core system applications.
                             mUninstallButton.setText(R.string.disable_text);
@@ -482,8 +482,10 @@
         ActivityManager am = (ActivityManager)
                 getActivity().getSystemService(Context.ACTIVITY_SERVICE);
         int compatMode = am.getPackageScreenCompatMode(packageName);
-        if (compatMode == ActivityManager.COMPAT_MODE_DISABLED
-                || compatMode == ActivityManager.COMPAT_MODE_ENABLED) {
+        // For now these are always off; this is the old UI model which we
+        // are no longer using.
+        if (false && (compatMode == ActivityManager.COMPAT_MODE_DISABLED
+                || compatMode == ActivityManager.COMPAT_MODE_ENABLED)) {
             mScreenCompatSection.setVisibility(View.VISIBLE);
             mAskCompatibilityCB.setChecked(am.getPackageAskScreenCompat(packageName));
             mAskCompatibilityCB.setOnCheckedChangeListener(this);
diff --git a/src/com/android/settings/wifi/AdvancedSettings.java b/src/com/android/settings/wifi/AdvancedSettings.java
index 4855c99..cd7b8a3 100644
--- a/src/com/android/settings/wifi/AdvancedSettings.java
+++ b/src/com/android/settings/wifi/AdvancedSettings.java
@@ -43,6 +43,7 @@
     private static final String KEY_FREQUENCY_BAND = "frequency_band";
     private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
     private static final String KEY_SLEEP_POLICY = "sleep_policy";
+    private static final String KEY_ENABLE_WIFI_WATCHDOG = "wifi_enable_watchdog_service";
 
     private WifiManager mWifiManager;
 
@@ -72,6 +73,13 @@
                 Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
         notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled());
 
+        CheckBoxPreference watchdogEnabled =
+                (CheckBoxPreference) findPreference(KEY_ENABLE_WIFI_WATCHDOG);
+        watchdogEnabled.setChecked(Secure.getInt(getContentResolver(),
+                Secure.WIFI_WATCHDOG_ON, 1) == 1);
+
+        watchdogEnabled.setEnabled(mWifiManager.isWifiEnabled());
+
         ListPreference frequencyPref = (ListPreference) findPreference(KEY_FREQUENCY_BAND);
 
         if (mWifiManager.isDualBandSupported()) {
@@ -111,12 +119,17 @@
             Secure.putInt(getContentResolver(),
                     Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                     ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
+        } else if (KEY_ENABLE_WIFI_WATCHDOG.equals(key)) {
+            Secure.putInt(getContentResolver(),
+                    Secure.WIFI_WATCHDOG_ON,
+                    ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
         } else {
             return super.onPreferenceTreeClick(screen, preference);
         }
         return true;
     }
 
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String key = preference.getKey();
 
diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java
index 1da8b68..bc92b3a 100644
--- a/src/com/android/settings/wifi/AdvancedWifiSettings.java
+++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java
@@ -76,6 +76,7 @@
         }
     }
 
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String key = preference.getKey();
         if (key == null) return true;