Home | History | Annotate | Download | only in accounts
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.accounts;
     18 
     19 import android.accounts.Account;
     20 import android.accounts.AccountManager;
     21 import android.accounts.OnAccountsUpdateListener;
     22 import android.app.ActionBar;
     23 import android.app.Activity;
     24 import android.content.ContentResolver;
     25 import android.content.Intent;
     26 import android.content.SyncAdapterType;
     27 import android.content.SyncInfo;
     28 import android.content.SyncStatusInfo;
     29 import android.graphics.drawable.Drawable;
     30 import android.os.Bundle;
     31 import android.preference.Preference;
     32 import android.preference.PreferenceActivity;
     33 import android.preference.PreferenceScreen;
     34 import android.util.Log;
     35 import android.view.Gravity;
     36 import android.view.LayoutInflater;
     37 import android.view.Menu;
     38 import android.view.MenuInflater;
     39 import android.view.MenuItem;
     40 import android.view.View;
     41 import android.view.ViewGroup;
     42 import android.widget.CompoundButton;
     43 import android.widget.Switch;
     44 import android.widget.TextView;
     45 
     46 import com.android.settings.AccountPreference;
     47 import com.android.settings.DialogCreatable;
     48 import com.android.settings.R;
     49 
     50 import java.util.ArrayList;
     51 import java.util.HashSet;
     52 
     53 public class ManageAccountsSettings extends AccountPreferenceBase
     54         implements OnAccountsUpdateListener, DialogCreatable {
     55 
     56     private static final int MENU_ADD_ACCOUNT = Menu.FIRST;
     57 
     58     private static final int REQUEST_SHOW_SYNC_SETTINGS = 1;
     59 
     60     private String[] mAuthorities;
     61     private TextView mErrorInfoView;
     62 
     63     private SettingsDialogFragment mDialogFragment;
     64     private Switch mAutoSyncSwitch;
     65 
     66     @Override
     67     public void onCreate(Bundle icicle) {
     68         super.onCreate(icicle);
     69 
     70         addPreferencesFromResource(R.xml.manage_accounts_settings);
     71         setHasOptionsMenu(true);
     72     }
     73 
     74     @Override
     75     public void onStart() {
     76         super.onStart();
     77         Activity activity = getActivity();
     78         AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, true);
     79         activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
     80                 ActionBar.DISPLAY_SHOW_CUSTOM);
     81         activity.getActionBar().setCustomView(mAutoSyncSwitch, new ActionBar.LayoutParams(
     82                 ActionBar.LayoutParams.WRAP_CONTENT,
     83                 ActionBar.LayoutParams.WRAP_CONTENT,
     84                 Gravity.CENTER_VERTICAL | Gravity.RIGHT));
     85     }
     86 
     87     @Override
     88     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     89             Bundle savedInstanceState) {
     90         final View view = inflater.inflate(R.layout.manage_accounts_screen, container, false);
     91         return view;
     92     }
     93 
     94     @Override
     95     public void onActivityCreated(Bundle savedInstanceState) {
     96         super.onActivityCreated(savedInstanceState);
     97 
     98         final Activity activity = getActivity();
     99         final View view = getView();
    100 
    101         mErrorInfoView = (TextView)view.findViewById(R.id.sync_settings_error_info);
    102         mErrorInfoView.setVisibility(View.GONE);
    103 
    104         mAutoSyncSwitch = new Switch(activity);
    105 
    106         // TODO Where to put the switch in tablet multipane layout?
    107         final int padding = activity.getResources().getDimensionPixelSize(
    108                 R.dimen.action_bar_switch_padding);
    109         mAutoSyncSwitch.setPadding(0, 0, padding, 0);
    110         mAutoSyncSwitch.setChecked(ContentResolver.getMasterSyncAutomatically());
    111         mAutoSyncSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    112             @Override
    113             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    114                 ContentResolver.setMasterSyncAutomatically(isChecked);
    115                 onSyncStateUpdated();
    116             }
    117         });
    118 
    119         mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY);
    120 
    121         updateAuthDescriptions();
    122     }
    123 
    124     @Override
    125     public void onStop() {
    126         super.onStop();
    127         final Activity activity = getActivity();
    128         AccountManager.get(activity).removeOnAccountsUpdatedListener(this);
    129         activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
    130         activity.getActionBar().setCustomView(null);
    131     }
    132 
    133     @Override
    134     public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
    135         if (preference instanceof AccountPreference) {
    136             startAccountSettings((AccountPreference) preference);
    137         } else {
    138             return false;
    139         }
    140         return true;
    141     }
    142 
    143     private void startAccountSettings(AccountPreference acctPref) {
    144         Bundle args = new Bundle();
    145         args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, acctPref.getAccount());
    146         ((PreferenceActivity) getActivity()).startPreferencePanel(
    147                 AccountSyncSettings.class.getCanonicalName(), args,
    148                 R.string.account_sync_settings_title, acctPref.getAccount().name,
    149                 this, REQUEST_SHOW_SYNC_SETTINGS);
    150     }
    151 
    152     @Override
    153     public void showDialog(int dialogId) {
    154         if (mDialogFragment != null) {
    155             Log.e(TAG, "Old dialog fragment not null!");
    156         }
    157         mDialogFragment = new SettingsDialogFragment(this, dialogId);
    158         mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
    159     }
    160 
    161     @Override
    162     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    163         MenuItem addAccountItem = menu.add(0, MENU_ADD_ACCOUNT, 0, R.string.add_account_label);
    164         addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
    165                 | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
    166     }
    167 
    168     @Override
    169     public boolean onOptionsItemSelected(MenuItem item) {
    170         final int itemId = item.getItemId();
    171         if (itemId == MENU_ADD_ACCOUNT) {
    172             onAddAccountClicked();
    173             return true;
    174         } else {
    175             return super.onOptionsItemSelected(item);
    176         }
    177     }
    178 
    179     @Override
    180     protected void onSyncStateUpdated() {
    181         // Catch any delayed delivery of update messages
    182         if (getActivity() == null) return;
    183         // Set background connection state
    184         if (mAutoSyncSwitch != null) {
    185             mAutoSyncSwitch.setChecked(ContentResolver.getMasterSyncAutomatically());
    186         }
    187 
    188         // iterate over all the preferences, setting the state properly for each
    189         SyncInfo currentSync = ContentResolver.getCurrentSync();
    190 
    191         boolean anySyncFailed = false; // true if sync on any account failed
    192 
    193         // only track userfacing sync adapters when deciding if account is synced or not
    194         final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
    195         HashSet<String> userFacing = new HashSet<String>();
    196         for (int k = 0, n = syncAdapters.length; k < n; k++) {
    197             final SyncAdapterType sa = syncAdapters[k];
    198             if (sa.isUserVisible()) {
    199                 userFacing.add(sa.authority);
    200             }
    201         }
    202         for (int i = 0, count = getPreferenceScreen().getPreferenceCount(); i < count; i++) {
    203             Preference pref = getPreferenceScreen().getPreference(i);
    204             if (! (pref instanceof AccountPreference)) {
    205                 continue;
    206             }
    207 
    208             AccountPreference accountPref = (AccountPreference) pref;
    209             Account account = accountPref.getAccount();
    210             int syncCount = 0;
    211             boolean syncIsFailing = false;
    212             final ArrayList<String> authorities = accountPref.getAuthorities();
    213             if (authorities != null) {
    214                 for (String authority : authorities) {
    215                     SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority);
    216                     boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority)
    217                             && ContentResolver.getMasterSyncAutomatically()
    218                             && (ContentResolver.getIsSyncable(account, authority) > 0);
    219                     boolean authorityIsPending = ContentResolver.isSyncPending(account, authority);
    220                     boolean activelySyncing = currentSync != null
    221                             && currentSync.authority.equals(authority)
    222                             && new Account(currentSync.account.name, currentSync.account.type)
    223                                     .equals(account);
    224                     boolean lastSyncFailed = status != null
    225                             && syncEnabled
    226                             && status.lastFailureTime != 0
    227                             && status.getLastFailureMesgAsInt(0)
    228                                != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
    229                     if (lastSyncFailed && !activelySyncing && !authorityIsPending) {
    230                         syncIsFailing = true;
    231                         anySyncFailed = true;
    232                     }
    233                     syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0;
    234                 }
    235             } else {
    236                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
    237                     Log.v(TAG, "no syncadapters found for " + account);
    238                 }
    239             }
    240             int syncStatus = AccountPreference.SYNC_DISABLED;
    241             if (syncIsFailing) {
    242                 syncStatus = AccountPreference.SYNC_ERROR;
    243             } else if (syncCount == 0) {
    244                 syncStatus = AccountPreference.SYNC_DISABLED;
    245             } else if (syncCount > 0) {
    246                 syncStatus = AccountPreference.SYNC_ENABLED;
    247             }
    248             accountPref.setSyncStatus(syncStatus);
    249         }
    250 
    251         mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE);
    252     }
    253 
    254     @Override
    255     public void onAccountsUpdated(Account[] accounts) {
    256         if (getActivity() == null) return;
    257         getPreferenceScreen().removeAll();
    258         for (int i = 0, n = accounts.length; i < n; i++) {
    259             final Account account = accounts[i];
    260             final ArrayList<String> auths = getAuthoritiesForAccountType(account.type);
    261 
    262             boolean showAccount = true;
    263             if (mAuthorities != null && auths != null) {
    264                 showAccount = false;
    265                 for (String requestedAuthority : mAuthorities) {
    266                     if (auths.contains(requestedAuthority)) {
    267                         showAccount = true;
    268                         break;
    269                     }
    270                 }
    271             }
    272 
    273             if (showAccount) {
    274                 final Drawable icon = getDrawableForType(account.type);
    275                 final AccountPreference preference =
    276                         new AccountPreference(getActivity(), account, icon, auths);
    277                 getPreferenceScreen().addPreference(preference);
    278             }
    279         }
    280         onSyncStateUpdated();
    281     }
    282 
    283     @Override
    284     protected void onAuthDescriptionsUpdated() {
    285         // Update account icons for all account preference items
    286         for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
    287             AccountPreference pref = (AccountPreference) getPreferenceScreen().getPreference(i);
    288             pref.setProviderIcon(getDrawableForType(pref.getAccount().type));
    289             pref.setSummary(getLabelForType(pref.getAccount().type));
    290         }
    291     }
    292 
    293     public void onAddAccountClicked() {
    294         Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
    295         intent.putExtra(AUTHORITIES_FILTER_KEY, mAuthorities);
    296         startActivity(intent);
    297     }
    298 }
    299