Merge "Allow applications to set the title of the subtype enabler Bug: 5058105"
diff --git a/res/drawable-hdpi/ic_settings_call.png b/res/drawable-hdpi/ic_settings_call.png
deleted file mode 100755
index f065807..0000000
--- a/res/drawable-hdpi/ic_settings_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-mdpi/setups_bg_account.png b/res/drawable-large-mdpi/setups_bg_account.png
deleted file mode 100644
index 42901f7..0000000
--- a/res/drawable-large-mdpi/setups_bg_account.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-mdpi/setups_bg_activating.png b/res/drawable-large-mdpi/setups_bg_activating.png
deleted file mode 100644
index 9b797c1..0000000
--- a/res/drawable-large-mdpi/setups_bg_activating.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-mdpi/setups_bg_welcome.png b/res/drawable-large-mdpi/setups_bg_welcome.png
deleted file mode 100644
index 8fcb8bf..0000000
--- a/res/drawable-large-mdpi/setups_bg_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_settings_call.png b/res/drawable-mdpi/ic_settings_call.png
deleted file mode 100755
index b4cf0db..0000000
--- a/res/drawable-mdpi/ic_settings_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/setups_bg_account.png b/res/drawable-xlarge-mdpi/setups_bg_account.png
deleted file mode 100644
index 3c95c53..0000000
--- a/res/drawable-xlarge-mdpi/setups_bg_account.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/setups_bg_activating.png b/res/drawable-xlarge-mdpi/setups_bg_activating.png
deleted file mode 100644
index f1cb815..0000000
--- a/res/drawable-xlarge-mdpi/setups_bg_activating.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/setups_bg_welcome.png b/res/drawable-xlarge-mdpi/setups_bg_welcome.png
deleted file mode 100644
index 5daa1c6..0000000
--- a/res/drawable-xlarge-mdpi/setups_bg_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/layout/zeroclick.xml b/res/layout/zeroclick.xml
new file mode 100644
index 0000000..99558f3
--- /dev/null
+++ b/res/layout/zeroclick.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:paddingLeft="6dip"
+    android:paddingRight="6dip"
+    android:layout_width="match_parent" android:layout_height="wrap_content"
+    android:scrollbars="vertical" >
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:fillViewport="true">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <View
+                android:paddingTop="53dip"
+                android:layout_width="match_parent"
+                android:layout_height="1dip"
+                android:background="#ff404040"
+                />
+
+            <CheckBox android:id="@+id/zeroclick_checkbox"
+                android:layout_width="match_parent"
+                android:layout_height="64dip"
+                android:gravity="center_vertical"
+                android:text="@string/zeroclick_label"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textColor="?android:attr/textColorSecondary"
+            />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dip"
+                android:background="#ff404040"
+                />
+
+            <TextView android:id="@+id/zeroclick_explained"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dip"
+                android:gravity="top"
+                android:text="@string/zeroclick_explained"
+            />
+
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b916a52..78a8069 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1087,6 +1087,12 @@
     <!-- NFC settings -->
     <!-- Used in the 1st-level settings screen to turn on NFC -->
     <string name="nfc_quick_toggle_title">NFC</string>
+    <!-- Used to enter the Zero-click sharing preferences screen -->
+    <string name="zeroclick_settings_title">Zero-click sharing</string>
+    <string name="zeroclick_settings_summary"></string>
+    <!-- Used in the zero-click sharing preferences screen -->
+    <string name="zeroclick_label">Zero-click sharing</string>
+    <string name="zeroclick_explained">Lorem ipsum dolor sit amet.</string>
 
     <!-- Wi-Fi Settings --> <skip />
     <!-- Used in the 1st-level settings screen to turn on Wi-Fi -->
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index 605ddb9..c0e4a5a 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -39,6 +39,14 @@
         android:persistent="false" />
 
     <PreferenceScreen
+        android:fragment="com.android.settings.nfc.ZeroClick"
+        android:key="zeroclick_settings"
+        android:title="@string/zeroclick_settings_title"
+        android:summary="@string/zeroclick_settings_summary" >
+    </PreferenceScreen>
+
+
+    <PreferenceScreen
         android:key="mobile_network_settings"
         android:title="@string/network_settings_title"
         android:dependency="toggle_airplane">
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index e5002c9..3b61064 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -223,6 +223,7 @@
     }
 
     private String getWord(int position) {
+        if (null == mCursor) return null;
         mCursor.moveToPosition(position);
         // Handle a possible race-condition
         if (mCursor.isAfterLast()) return null;
@@ -298,7 +299,7 @@
                     FREQUENCY_FOR_USER_DICTIONARY_ADDS, UserDictionary.Words.LOCALE_TYPE_CURRENT);
             Locale.setDefault(prevLocale);
         }
-        if (!mCursor.requery()) {
+        if (null != mCursor && !mCursor.requery()) {
             throw new IllegalStateException("can't requery on already-closed cursor.");
         }
         mAddedWordAlready = true;
@@ -333,23 +334,25 @@
             super(context, layout, c, from, to);
 
             mSettings = settings;
-            int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
-            String alphabet = context.getString(
-                    com.android.internal.R.string.fast_scroll_alphabet);
-            mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
+            if (null != c) {
+                final String alphabet = context.getString(
+                        com.android.internal.R.string.fast_scroll_alphabet);
+                final int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
+                mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
+            }
             setViewBinder(mViewBinder);
         }
 
         public int getPositionForSection(int section) {
-            return mIndexer.getPositionForSection(section);
+            return null == mIndexer ? 0 : mIndexer.getPositionForSection(section);
         }
 
         public int getSectionForPosition(int position) {
-            return mIndexer.getSectionForPosition(position);
+            return null == mIndexer ? 0 : mIndexer.getSectionForPosition(position);
         }
 
         public Object[] getSections() {
-            return mIndexer.getSections();
+            return null == mIndexer ? null : mIndexer.getSections();
         }
 
         public void onClick(View v) {
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 5560a03..c07388e 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -37,6 +37,7 @@
 
     private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
     private static final String KEY_TOGGLE_NFC = "toggle_nfc";
+    private static final String KEY_ZEROCLICK_SETTINGS = "zeroclick_settings";
     private static final String KEY_VPN_SETTINGS = "vpn_settings";
     private static final String KEY_TETHER_SETTINGS = "tether_settings";
     private static final String KEY_PROXY_SETTINGS = "proxy_settings";
@@ -87,9 +88,11 @@
         final Activity activity = getActivity();
         mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
         CheckBoxPreference nfc = (CheckBoxPreference) findPreference(KEY_TOGGLE_NFC);
+        PreferenceScreen zeroclick = (PreferenceScreen)
+                findPreference(KEY_ZEROCLICK_SETTINGS);
 
         mAirplaneModeEnabler = new AirplaneModeEnabler(activity, mAirplaneModePreference);
-        mNfcEnabler = new NfcEnabler(activity, nfc);
+        mNfcEnabler = new NfcEnabler(activity, nfc, zeroclick);
 
         String toggleable = Settings.System.getString(activity.getContentResolver(),
                 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
@@ -107,6 +110,7 @@
         // Remove NFC if its not available
         if (NfcAdapter.getDefaultAdapter(activity) == null) {
             getPreferenceScreen().removePreference(nfc);
+            getPreferenceScreen().removePreference(zeroclick);
         }
 
         // Remove Mobile Network Settings if it's a wifi-only device.
diff --git a/src/com/android/settings/accounts/AddAccountSettings.java b/src/com/android/settings/accounts/AddAccountSettings.java
index 72ef130..382481e 100644
--- a/src/com/android/settings/accounts/AddAccountSettings.java
+++ b/src/com/android/settings/accounts/AddAccountSettings.java
@@ -22,6 +22,7 @@
 import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
@@ -44,18 +45,37 @@
  * when returning from each account setup, which doesn't look good.
  */
 public class AddAccountSettings extends Activity {
+    /**
+     * 
+     */
+    private static final String KEY_ADD_CALLED = "AddAccountCalled";
+
+    /**
+     * Extra parameter to identify the caller. Applications may display a
+     * different UI if the calls is made from Settings or from a specific
+     * application.
+     */
+    private static final String KEY_CALLER_IDENTITY = "pendingIntent";
+
     private static final String TAG = "AccountSettings";
 
     /* package */ static final String EXTRA_SELECTED_ACCOUNT = "selected_account";
 
     private static final int CHOOSE_ACCOUNT_REQUEST = 1;
 
+    private PendingIntent mPendingIntent;
+
     private AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
         public void run(AccountManagerFuture<Bundle> future) {
             try {
                 Bundle bundle = future.getResult();
                 bundle.keySet();
                 setResult(RESULT_OK);
+
+                if (mPendingIntent != null) {
+                    mPendingIntent.cancel();
+                }
+
                 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "account added: " + bundle);
             } catch (OperationCanceledException e) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount was canceled");
@@ -69,10 +89,22 @@
         }
     };
 
+    private boolean mAddAccountCalled = false;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        if (savedInstanceState != null) {
+            mAddAccountCalled = savedInstanceState.getBoolean(KEY_ADD_CALLED);
+            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "restored");
+        }
+
+        if (mAddAccountCalled) {
+            // We already called add account - maybe the callback was lost.
+            finish();
+            return;
+        }
         final String[] authorities =
                 getIntent().getStringArrayExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
         final String[] accountTypes =
@@ -102,14 +134,24 @@
         }
     }
 
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(KEY_ADD_CALLED, mAddAccountCalled);
+        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "saved");
+    }
+
     private void addAccount(String accountType) {
+        Bundle addAccountOptions = new Bundle();
+        mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(), 0);
+        addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
         AccountManager.get(this).addAccount(
                 accountType,
                 null, /* authTokenType */
                 null, /* requiredFeatures */
-                null, /* addAccountOptions */
+                addAccountOptions,
                 this,
                 mCallback,
                 null /* handler */);
+        mAddAccountCalled  = true;
     }
 }
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index 4ccebf0..e966ec7 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -126,7 +126,12 @@
     private void updateUserDictionaryPreference(Preference userDictionaryPreference) {
         final Activity activity = getActivity();
         final Set<String> localeList = UserDictionaryList.getUserDictionaryLocalesList(activity);
-        if (localeList.size() <= 1) {
+        if (null == localeList) {
+            // The locale list is null if and only if the user dictionary service is
+            // not present or disabled. In this case we need to remove the preference.
+            ((PreferenceGroup)findPreference("language_settings_category")).removePreference(
+                    userDictionaryPreference);
+        } else if (localeList.size() <= 1) {
             userDictionaryPreference.setTitle(R.string.user_dict_single_settings_title);
             userDictionaryPreference.setFragment(UserDictionarySettings.class.getName());
             // If the size of localeList is 0, we don't set the locale parameter in the
diff --git a/src/com/android/settings/inputmethod/UserDictionaryList.java b/src/com/android/settings/inputmethod/UserDictionaryList.java
index 5db2841..e0afe48 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryList.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryList.java
@@ -49,7 +49,10 @@
                 new String[] { UserDictionary.Words.LOCALE },
                 null, null, null);
         final Set<String> localeList = new TreeSet<String>();
-        if (cursor.moveToFirst()) {
+        if (null == cursor) {
+            // The user dictionary service is not present or disabled. Return null.
+            return null;
+        } else if (cursor.moveToFirst()) {
             final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
             do {
                 String locale = cursor.getString(columnIndex);
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index dba1329..99cf8f0 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
+import android.preference.PreferenceScreen;
 import android.util.Log;
 
 /**
@@ -36,6 +37,7 @@
 
     private final Context mContext;
     private final CheckBoxPreference mCheckbox;
+    private final PreferenceScreen mZeroClick;
     private final NfcAdapter mNfcAdapter;
     private final IntentFilter mIntentFilter;
     private final Handler mHandler = new Handler();
@@ -54,9 +56,11 @@
 
     private boolean mNfcState;
 
-    public NfcEnabler(Context context, CheckBoxPreference checkBoxPreference) {
+    public NfcEnabler(Context context, CheckBoxPreference checkBoxPreference,
+            PreferenceScreen zeroclick) {
         mContext = context;
         mCheckbox = checkBoxPreference;
+        mZeroClick = zeroclick;
         mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
 
         if (mNfcAdapter == null) {
@@ -127,5 +131,6 @@
     private void handleNfcStateChanged(boolean newState) {
         mCheckbox.setChecked(newState);
         mCheckbox.setEnabled(true);
+        mZeroClick.setEnabled(newState);
     }
 }
diff --git a/src/com/android/settings/nfc/ZeroClick.java b/src/com/android/settings/nfc/ZeroClick.java
new file mode 100644
index 0000000..7868662
--- /dev/null
+++ b/src/com/android/settings/nfc/ZeroClick.java
@@ -0,0 +1,81 @@
+/*
+ * 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.nfc;
+
+import android.app.Fragment;
+import android.content.ContentResolver;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.util.Log;
+import com.android.settings.R;
+
+public class ZeroClick extends Fragment
+        implements CompoundButton.OnCheckedChangeListener {
+    private View mView;
+    private CheckBox mCheckbox;
+    private NfcAdapter mNfcAdapter;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mView = inflater.inflate(R.layout.zeroclick, container, false);
+        initView(mView);
+        return mView;
+    }
+
+    private void initView(View view) {
+        mCheckbox = (CheckBox) mView.findViewById(R.id.zeroclick_checkbox);
+        mCheckbox.setOnCheckedChangeListener(this);
+        mNfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
+        mCheckbox.setChecked(mNfcAdapter.zeroClickEnabled());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton buttonView, boolean desiredState) {
+        boolean success = false;
+        mCheckbox.setEnabled(false);
+        if (desiredState) {
+            success = mNfcAdapter.enableZeroClick();
+        } else {
+            success = mNfcAdapter.disableZeroClick();
+        }
+        if (success) {
+            mCheckbox.setChecked(desiredState);
+        }
+        mCheckbox.setEnabled(true);
+    }
+}
diff --git a/tests/res/drawable/ic_settings_applications.png b/tests/res/drawable-hdpi/ic_settings_applications.png
similarity index 100%
rename from tests/res/drawable/ic_settings_applications.png
rename to tests/res/drawable-hdpi/ic_settings_applications.png
Binary files differ
diff --git a/tests/res/drawable-mdpi/ic_settings_applications.png b/tests/res/drawable-mdpi/ic_settings_applications.png
new file mode 100755
index 0000000..745ff2a
--- /dev/null
+++ b/tests/res/drawable-mdpi/ic_settings_applications.png
Binary files differ