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; 18 19 import com.android.providers.subscribedfeeds.R; 20 21 import android.accounts.AccountManager; 22 import android.accounts.Account; 23 import android.app.AlertDialog; 24 import android.app.Dialog; 25 import android.content.SyncInfo; 26 import android.content.ContentResolver; 27 import android.content.Context; 28 import android.content.DialogInterface; 29 import android.content.Intent; 30 import android.content.SyncAdapterType; 31 import android.content.SyncStatusInfo; 32 import android.graphics.drawable.Drawable; 33 import android.net.ConnectivityManager; 34 import android.os.Bundle; 35 import android.preference.CheckBoxPreference; 36 import android.preference.Preference; 37 import android.preference.PreferenceCategory; 38 import android.preference.PreferenceScreen; 39 import android.view.View; 40 import android.widget.Button; 41 import android.widget.TextView; 42 import android.util.Log; 43 44 import java.util.ArrayList; 45 import java.util.HashSet; 46 47 public class ManageAccountsSettings extends AccountPreferenceBase implements View.OnClickListener { 48 private static final String AUTO_SYNC_CHECKBOX_KEY = "syncAutomaticallyCheckBox"; 49 private static final String MANAGE_ACCOUNTS_CATEGORY_KEY = "manageAccountsCategory"; 50 private static final String BACKGROUND_DATA_CHECKBOX_KEY = "backgroundDataCheckBox"; 51 private static final int DIALOG_DISABLE_BACKGROUND_DATA = 1; 52 53 private CheckBoxPreference mBackgroundDataCheckBox; 54 private PreferenceCategory mManageAccountsCategory; 55 private String[] mAuthorities; 56 private TextView mErrorInfoView; 57 private Button mAddAccountButton; 58 private CheckBoxPreference mAutoSyncCheckbox; 59 60 @Override 61 public void onCreate(Bundle icicle) { 62 super.onCreate(icicle); 63 64 setContentView(R.layout.manage_accounts_screen); 65 addPreferencesFromResource(R.xml.manage_accounts_settings); 66 67 mErrorInfoView = (TextView)findViewById(R.id.sync_settings_error_info); 68 mErrorInfoView.setVisibility(View.GONE); 69 mErrorInfoView.setCompoundDrawablesWithIntrinsicBounds( 70 getResources().getDrawable(R.drawable.ic_list_syncerror), null, null, null); 71 72 mBackgroundDataCheckBox = (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY); 73 mAutoSyncCheckbox = (CheckBoxPreference) findPreference(AUTO_SYNC_CHECKBOX_KEY); 74 75 mManageAccountsCategory = 76 (PreferenceCategory) findPreference(MANAGE_ACCOUNTS_CATEGORY_KEY); 77 mAuthorities = getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY); 78 mAddAccountButton = (Button) findViewById(R.id.add_account_button); 79 mAddAccountButton.setOnClickListener(this); 80 81 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true); 82 updateAuthDescriptions(); 83 } 84 85 @Override 86 public void onDestroy() { 87 AccountManager.get(this).removeOnAccountsUpdatedListener(this); 88 super.onDestroy(); 89 } 90 91 @Override 92 public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) { 93 if (preference == mBackgroundDataCheckBox) { 94 ConnectivityManager connManager = 95 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 96 boolean oldBackgroundDataSetting = connManager.getBackgroundDataSetting(); 97 boolean backgroundDataSetting = mBackgroundDataCheckBox.isChecked(); 98 if (oldBackgroundDataSetting != backgroundDataSetting) { 99 if (backgroundDataSetting) { 100 setBackgroundDataInt(true); 101 onSyncStateUpdated(); 102 } else { 103 // This will get unchecked only if the user hits "Ok" 104 mBackgroundDataCheckBox.setChecked(true); 105 showDialog(DIALOG_DISABLE_BACKGROUND_DATA); 106 } 107 } 108 } else if (preference == mAutoSyncCheckbox) { 109 ContentResolver.setMasterSyncAutomatically(mAutoSyncCheckbox.isChecked()); 110 onSyncStateUpdated(); 111 } else { 112 return false; 113 } 114 return true; 115 } 116 117 @Override 118 protected Dialog onCreateDialog(int id) { 119 switch (id) { 120 case DIALOG_DISABLE_BACKGROUND_DATA: 121 final CheckBoxPreference pref = 122 (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY); 123 return new AlertDialog.Builder(this) 124 .setTitle(R.string.background_data_dialog_title) 125 .setIcon(android.R.drawable.ic_dialog_alert) 126 .setMessage(R.string.background_data_dialog_message) 127 .setPositiveButton(android.R.string.ok, 128 new DialogInterface.OnClickListener() { 129 public void onClick(DialogInterface dialog, int which) { 130 setBackgroundDataInt(false); 131 pref.setChecked(false); 132 onSyncStateUpdated(); 133 } 134 }) 135 .setNegativeButton(android.R.string.cancel, null) 136 .create(); 137 } 138 139 return null; 140 } 141 142 private void setBackgroundDataInt(boolean enabled) { 143 ConnectivityManager connManager = 144 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 145 connManager.setBackgroundDataSetting(enabled); 146 } 147 148 @Override 149 protected void onSyncStateUpdated() { 150 // Set background connection state 151 ConnectivityManager connManager = 152 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 153 boolean backgroundDataSetting = connManager.getBackgroundDataSetting(); 154 mBackgroundDataCheckBox.setChecked(backgroundDataSetting); 155 boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically(); 156 mAutoSyncCheckbox.setChecked(masterSyncAutomatically); 157 158 // iterate over all the preferences, setting the state properly for each 159 SyncInfo currentSync = ContentResolver.getCurrentSync(); 160 161 boolean anySyncFailed = false; // true if sync on any account failed 162 163 // only track userfacing sync adapters when deciding if account is synced or not 164 final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes(); 165 HashSet<String> userFacing = new HashSet<String>(); 166 for (int k = 0, n = syncAdapters.length; k < n; k++) { 167 final SyncAdapterType sa = syncAdapters[k]; 168 if (sa.isUserVisible()) { 169 userFacing.add(sa.authority); 170 } 171 } 172 for (int i = 0, count = mManageAccountsCategory.getPreferenceCount(); i < count; i++) { 173 Preference pref = mManageAccountsCategory.getPreference(i); 174 if (! (pref instanceof AccountPreference)) { 175 continue; 176 } 177 178 AccountPreference accountPref = (AccountPreference) pref; 179 Account account = accountPref.getAccount(); 180 int syncCount = 0; 181 boolean syncIsFailing = false; 182 final ArrayList<String> authorities = accountPref.getAuthorities(); 183 if (authorities != null) { 184 for (String authority : authorities) { 185 SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority); 186 boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority) 187 && masterSyncAutomatically 188 && backgroundDataSetting 189 && (ContentResolver.getIsSyncable(account, authority) > 0); 190 boolean authorityIsPending = ContentResolver.isSyncPending(account, authority); 191 boolean activelySyncing = currentSync != null 192 && currentSync.authority.equals(authority) 193 && new Account(currentSync.account.name, currentSync.account.type).equals(account); 194 boolean lastSyncFailed = status != null 195 && syncEnabled 196 && status.lastFailureTime != 0 197 && status.getLastFailureMesgAsInt(0) 198 != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS; 199 if (lastSyncFailed && !activelySyncing && !authorityIsPending) { 200 syncIsFailing = true; 201 anySyncFailed = true; 202 } 203 syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0; 204 } 205 } else { 206 if (Log.isLoggable(TAG, Log.VERBOSE)) { 207 Log.v(TAG, "no syncadapters found for " + account); 208 } 209 } 210 int syncStatus = AccountPreference.SYNC_DISABLED; 211 if (syncIsFailing) { 212 syncStatus = AccountPreference.SYNC_ERROR; 213 } else if (syncCount == 0) { 214 syncStatus = AccountPreference.SYNC_DISABLED; 215 } else if (syncCount > 0) { 216 syncStatus = AccountPreference.SYNC_ENABLED; 217 } 218 accountPref.setSyncStatus(syncStatus); 219 } 220 221 mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE); 222 } 223 224 public void onAccountsUpdated(Account[] accounts) { 225 mManageAccountsCategory.removeAll(); 226 for (int i = 0, n = accounts.length; i < n; i++) { 227 final Account account = accounts[i]; 228 final ArrayList<String> auths = getAuthoritiesForAccountType(account.type); 229 230 boolean showAccount = true; 231 if (mAuthorities != null && auths != null) { 232 showAccount = false; 233 for (String requestedAuthority : mAuthorities) { 234 if (auths.contains(requestedAuthority)) { 235 showAccount = true; 236 break; 237 } 238 } 239 } 240 241 if (showAccount) { 242 Drawable icon = getDrawableForType(account.type); 243 AccountPreference preference = new AccountPreference(this, account, icon, auths); 244 mManageAccountsCategory.addPreference(preference); 245 } 246 } 247 onSyncStateUpdated(); 248 } 249 250 @Override 251 protected void onAuthDescriptionsUpdated() { 252 // Update account icons for all account preference items 253 for (int i = 0; i < mManageAccountsCategory.getPreferenceCount(); i++) { 254 AccountPreference pref = (AccountPreference) mManageAccountsCategory.getPreference(i); 255 pref.setProviderIcon(getDrawableForType(pref.getAccount().type)); 256 pref.setSummary(getLabelForType(pref.getAccount().type)); 257 } 258 } 259 260 public void onClick(View v) { 261 if (v == mAddAccountButton) { 262 Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); 263 intent.putExtra(AUTHORITIES_FILTER_KEY, mAuthorities); 264 startActivity(intent); 265 } 266 } 267 } 268