merge in lmp-mr1-release history after reset to lmp-mr1-dev
diff --git a/Settings/res/drawable-hdpi/ic_settings_google_account.png b/Settings/res/drawable-hdpi/ic_settings_google_account.png
new file mode 100644
index 0000000..9daeec3
--- /dev/null
+++ b/Settings/res/drawable-hdpi/ic_settings_google_account.png
Binary files differ
diff --git a/Settings/res/drawable-mdpi/ic_settings_google_account.png b/Settings/res/drawable-mdpi/ic_settings_google_account.png
new file mode 100644
index 0000000..0d8af1b
--- /dev/null
+++ b/Settings/res/drawable-mdpi/ic_settings_google_account.png
Binary files differ
diff --git a/Settings/res/drawable-xhdpi/ic_settings_google_account.png b/Settings/res/drawable-xhdpi/ic_settings_google_account.png
new file mode 100644
index 0000000..2e6c304
--- /dev/null
+++ b/Settings/res/drawable-xhdpi/ic_settings_google_account.png
Binary files differ
diff --git a/Settings/res/drawable-xxhdpi/ic_settings_google_account.png b/Settings/res/drawable-xxhdpi/ic_settings_google_account.png
new file mode 100644
index 0000000..ea6d148
--- /dev/null
+++ b/Settings/res/drawable-xxhdpi/ic_settings_google_account.png
Binary files differ
diff --git a/Settings/res/values/config.xml b/Settings/res/values/config.xml
index 565cde3..95a5e4b 100644
--- a/Settings/res/values/config.xml
+++ b/Settings/res/values/config.xml
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 <resources>
-    <bool name="multiple_accounts_enabled">false</bool>
     <integer name="settings_fade_in_duration">350</integer>
     <integer name="settings_fade_out_duration">350</integer>
     <integer name="action_title_max_lines">3</integer>
diff --git a/Settings/src/com/android/tv/settings/BrowseInfo.java b/Settings/src/com/android/tv/settings/BrowseInfo.java
index 47e703a..8f38f82 100644
--- a/Settings/src/com/android/tv/settings/BrowseInfo.java
+++ b/Settings/src/com/android/tv/settings/BrowseInfo.java
@@ -18,15 +18,23 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.Intent.ShortcutIconResource;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.preference.PreferenceActivity;
@@ -34,6 +42,7 @@
 import android.support.v17.leanback.widget.HeaderItem;
 import android.support.v17.leanback.widget.ObjectAdapter;
 import android.support.v17.leanback.widget.ListRow;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -45,6 +54,7 @@
 import com.android.tv.settings.accessories.BluetoothConnectionsManager;
 import com.android.tv.settings.accounts.AccountImageUriGetter;
 import com.android.tv.settings.accounts.AccountSettingsActivity;
+import com.android.tv.settings.accounts.AddAccountWithTypeActivity;
 import com.android.tv.settings.accounts.AuthenticatorHelper;
 import com.android.tv.settings.connectivity.ConnectivityStatusIconUriGetter;
 import com.android.tv.settings.connectivity.ConnectivityStatusTextGetter;
@@ -52,11 +62,13 @@
 import com.android.tv.settings.device.sound.SoundActivity;
 import com.android.tv.settings.users.RestrictedProfileActivity;
 import com.android.tv.settings.util.UriUtils;
+import com.android.tv.settings.util.AccountImageHelper;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Set;
 
 /**
@@ -170,7 +182,6 @@
     private int mAccountHeaderId;
     private final BluetoothAdapter mBtAdapter;
     private final Object mGuard = new Object();
-    private final boolean mAllowMultipleAccounts;
     private MenuItem mWifiItem = null;
     private ArrayObjectAdapter mWifiRow = null;
     private final Handler mHandler = new Handler();
@@ -186,8 +197,6 @@
         mAuthenticatorHelper.onAccountsUpdated(context, null);
         mBtAdapter = BluetoothAdapter.getDefaultAdapter();
         mNextItemId = 0;
-        mAllowMultipleAccounts =
-                context.getResources().getBoolean(R.bool.multiple_accounts_enabled);
         mPreferenceUtils = new PreferenceUtils(context);
         mDeveloperEnabled = mPreferenceUtils.isDeveloperEnabled();
         mInputSettingNeeded = isInputSettingNeeded();
@@ -238,10 +247,6 @@
         }
     }
 
-    private boolean canAddAccount() {
-        return !isRestricted();
-    }
-
     private boolean isRestricted() {
         return RestrictedProfileActivity.isRestrictedProfileInEffect(mContext);
     }
@@ -446,48 +451,85 @@
     }
 
     private void addAccounts(ArrayObjectAdapter row) {
-        String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
-        if (accountTypes.length == 0) {
-            // That's weird, let's try updating.
-            mAuthenticatorHelper.onAccountsUpdated(mContext, null);
-            accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
-        }
+        AccountManager am = AccountManager.get(mContext);
+        AuthenticatorDescription[] authTypes = am.getAuthenticatorTypes();
+        ArrayList<String> allowableAccountTypes = new ArrayList<>(authTypes.length);
+        PackageManager pm = mContext.getPackageManager();
 
         int googleAccountCount = 0;
 
-        for (String accountType : accountTypes) {
-            CharSequence label = mAuthenticatorHelper.getLabelForType(mContext, accountType);
-            if (label == null) {
+        for (AuthenticatorDescription authDesc : authTypes) {
+            Resources resources = null;
+            try {
+                resources = pm.getResourcesForApplication(authDesc.packageName);
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Authenticator description with bad package name", e);
                 continue;
             }
 
-            Account[] accounts = AccountManager.get(mContext).getAccountsByType(accountType);
-            if (ACCOUNT_TYPE_GOOGLE.equals(accountType)) {
-                googleAccountCount = accounts.length;
+            allowableAccountTypes.add(authDesc.type);
+
+            // Main title text comes from the authenticator description (e.g. "Google").
+            String authTitle = null;
+            try {
+                authTitle = resources.getString(authDesc.labelId);
+                if (TextUtils.isEmpty(authTitle)) {
+                    authTitle = null;  // Handled later when we add the row.
+                }
+            } catch (NotFoundException e) {
+                Log.e(TAG, "Authenticator description with bad label id", e);
             }
+
+            Account[] accounts = am.getAccountsByType(authDesc.type);
+
+            // Icon URI to be displayed for each account is based on the type of authenticator.
+            String imageUri = null;
+            if (ACCOUNT_TYPE_GOOGLE.equals(authDesc.type)) {
+                googleAccountCount = accounts.length;
+                imageUri = googleAccountIconUri(mContext);
+            } else {
+                imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                        authDesc.packageName + '/' +
+                        resources.getResourceTypeName(authDesc.iconId) + '/' +
+                        resources.getResourceEntryName(authDesc.iconId))
+                        .toString();
+            }
+
+            // Display an entry for each installed account we have.
             for (final Account account : accounts) {
                 Intent i = new Intent(mContext, AccountSettingsActivity.class)
                         .putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account.name);
                 i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-                row.add(new MenuItem.Builder().id(mNextItemId++).title(account.name)
-                        .imageUriGetter(new AccountImageUriGetter(mContext, account))
+                row.add(new MenuItem.Builder().id(mNextItemId++)
+                        .title(authTitle != null ? authTitle : account.name)
+                        .imageUri(imageUri)
+                        .description(authTitle != null ? account.name : null)
                         .intent(i)
                         .build());
             }
         }
 
-        if (canAddAccount() && (mAllowMultipleAccounts || googleAccountCount == 0)) {
-            ComponentName componentName = new ComponentName("com.android.tv.settings",
-                    "com.android.tv.settings.accounts.AddAccountWithTypeActivity");
-            Intent i = new Intent().setComponent(componentName);
-            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-            if (accountTypes.length == 1) {
-                i.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountTypes[0]);
+        // Never allow restricted profile to add accounts.
+        if (!isRestricted()) {
+
+            // If there's already a Google account installed, disallow installing a second one.
+            if (googleAccountCount > 0) {
+                allowableAccountTypes.remove(ACCOUNT_TYPE_GOOGLE);
             }
-            row.add(new MenuItem.Builder().id(mNextItemId++)
-                    .title(mContext.getString(R.string.add_account))
-                    .imageResourceId(mContext, R.drawable.ic_settings_add)
-                    .intent(i).build());
+
+            // If there are available account types, add the "add account" button.
+            if (!allowableAccountTypes.isEmpty()) {
+                Intent i = new Intent().setComponent(new ComponentName("com.android.tv.settings",
+                        "com.android.tv.settings.accounts.AddAccountWithTypeActivity"));
+                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+                i.putExtra(AddAccountWithTypeActivity.EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY,
+                        allowableAccountTypes.toArray(new String[allowableAccountTypes.size()]));
+
+                row.add(new MenuItem.Builder().id(mNextItemId++)
+                        .title(mContext.getString(R.string.add_account))
+                        .imageResourceId(mContext, R.drawable.ic_settings_add)
+                        .intent(i).build());
+            }
         }
     }
 
@@ -522,4 +564,12 @@
             }
         }
     }
+
+    private static String googleAccountIconUri(Context context) {
+        ShortcutIconResource iconResource = new ShortcutIconResource();
+        iconResource.packageName = context.getPackageName();
+        iconResource.resourceName = context.getResources().getResourceName(
+                R.drawable.ic_settings_google_account);
+        return UriUtils.getShortcutIconResourceUri(iconResource).toString();
+    }
 }
diff --git a/Settings/src/com/android/tv/settings/accounts/AddAccountWithTypeActivity.java b/Settings/src/com/android/tv/settings/accounts/AddAccountWithTypeActivity.java
index 0f0b09f..737175f 100644
--- a/Settings/src/com/android/tv/settings/accounts/AddAccountWithTypeActivity.java
+++ b/Settings/src/com/android/tv/settings/accounts/AddAccountWithTypeActivity.java
@@ -27,8 +27,12 @@
 import java.io.IOException;
 import android.util.Log;
 
+
 public class AddAccountWithTypeActivity extends Activity {
 
+    // Must match com.google.android.gms.common.AccountPicker.
+    public static final String EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY = "allowableAccountTypes";
+
     private static final String TAG = "AddAccountWithTypeActivity";
 
     private static final int REQUEST_CHOOSE_ACCOUNT_TYPE = 0;
@@ -36,8 +40,6 @@
     private static final String CHOOSE_ACCOUNT_TYPE_ACTION =
             "com.google.android.gms.common.account.CHOOSE_ACCOUNT_TYPE";
 
-    private boolean mLaunchAccountTypePicker;
-
     private final AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
         @Override
         public void run(AccountManagerFuture<Bundle> future) {
@@ -46,19 +48,19 @@
                         .getParcelable(AccountManager.KEY_INTENT);
                 if (addAccountIntent == null) {
                     Log.e(TAG, "Failed to retrieve add account intent from authenticator");
-                    handleAddAccountError();
+                    setResultAndFinish(Activity.RESULT_CANCELED);
                 } else {
                     startActivityForResult(addAccountIntent, REQUEST_ADD_ACCOUNT);
                 }
             } catch (OperationCanceledException e) {
                 Log.e(TAG, "Failed to get add account intent: " + e);
-                handleAddAccountError();
+                setResultAndFinish(Activity.RESULT_CANCELED);
             } catch (IOException e) {
                 Log.e(TAG, "Failed to get add account intent: " + e);
-                handleAddAccountError();
+                setResultAndFinish(Activity.RESULT_CANCELED);
             } catch (AuthenticatorException e) {
                 Log.e(TAG, "Failed to get add account intent: " + e);
-                handleAddAccountError();
+                setResultAndFinish(Activity.RESULT_CANCELED);
             }
         }
     };
@@ -70,48 +72,30 @@
         if (accountType != null) {
             startAddAccount(accountType);
         } else {
-            startAccountTypePicker();
+            String[] allowedTypes = getIntent().getStringArrayExtra(
+                    EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
+            startAccountTypePicker(allowedTypes);
         }
     }
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (Activity.RESULT_CANCELED == resultCode) {
-            setResult(resultCode);
-            finish();
-            return;
-        }
-
-        switch (requestCode) {
-            case REQUEST_ADD_ACCOUNT:
-                if (resultCode == Activity.RESULT_OK) {
-                    setResult(resultCode);
-                    finish();
-                } else {
-                    handleAddAccountError(resultCode);
-                }
-                break;
-            case REQUEST_CHOOSE_ACCOUNT_TYPE:
-                if (resultCode == Activity.RESULT_OK) {
-                    String accountType = data.getExtras()
-                            .getString(AccountManager.KEY_ACCOUNT_TYPE);
-                    startAddAccount(accountType);
-                } else {
-                    setResult(resultCode);
-                    finish();
-                }
-                break;
+        // User selected an account type, so kick off the add account flow for that.
+        if (requestCode == REQUEST_CHOOSE_ACCOUNT_TYPE && resultCode == Activity.RESULT_OK) {
+            String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
+            startAddAccount(accountType);
+        } else {
+            setResultAndFinish(resultCode);
         }
     }
 
-    private void startAccountTypePicker() {
-        mLaunchAccountTypePicker = true;
+    private void startAccountTypePicker(String[] allowedTypes) {
         Intent i = new Intent(CHOOSE_ACCOUNT_TYPE_ACTION);
+        i.putExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY, allowedTypes);
         startActivityForResult(i, REQUEST_CHOOSE_ACCOUNT_TYPE);
     }
 
     private void startAddAccount(String accountType) {
-        mLaunchAccountTypePicker = false;
         AccountManager.get(this).addAccount(
                 accountType,
                 null, /* authTokenType */
@@ -120,18 +104,8 @@
                 null, mCallback, null);
     }
 
-    private void handleAddAccountError() {
-        handleAddAccountError(Activity.RESULT_CANCELED);
-    }
-
-    private void handleAddAccountError(int resultCode) {
-        if (mLaunchAccountTypePicker) {
-            Log.e(TAG, "request add account failed to add account");
-            // try again
-            startAccountTypePicker();
-        } else {
-            setResult(resultCode);
-            finish();
-        }
+    private void setResultAndFinish(int resultCode) {
+        setResult(resultCode);
+        finish();
     }
 }