1d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana/* 2d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Copyright (C) 2009 The Android Open Source Project 3d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 4d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License"); 5d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * you may not use this file except in compliance with the License. 6d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * You may obtain a copy of the License at 7d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 8d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * http://www.apache.org/licenses/LICENSE-2.0 9d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 10d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Unless required by applicable law or agreed to in writing, software 11d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS, 12d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * See the License for the specific language governing permissions and 14d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * limitations under the License. 15d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana */ 16d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 17d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanapackage com.android.development; 18d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 19d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.Activity; 20d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.PendingIntent; 21d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.Dialog; 22d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.AlertDialog; 2382ace4a0d750e377953141eeff84eb6c72655152Dianne Hackbornimport android.content.res.Resources; 24d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.res.TypedArray; 25d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.pm.RegisteredServicesCache; 26d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.pm.RegisteredServicesCacheListener; 27d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.SyncAdapterType; 28d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ISyncAdapter; 29d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ISyncContext; 30d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ServiceConnection; 31d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ComponentName; 32d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.SyncResult; 33d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.Intent; 34d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.Context; 35d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.Bundle; 36d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.IBinder; 37d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.RemoteException; 38d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.ArrayAdapter; 39d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.AdapterView; 40d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.Spinner; 41d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.Button; 42d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.TextView; 43d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.ListView; 44d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.util.AttributeSet; 45d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.provider.Settings; 46d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.accounts.Account; 47d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.accounts.AccountManager; 48d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.view.View; 49d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.view.LayoutInflater; 50d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 51d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport java.util.Collection; 52d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 53d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanapublic class SyncAdapterDriver extends Activity 54cf229bb013317db77034980c212ab07bea260261Fred Quintana implements RegisteredServicesCacheListener<SyncAdapterType>, 55cf229bb013317db77034980c212ab07bea260261Fred Quintana AdapterView.OnItemClickListener { 56d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Spinner mSyncAdapterSpinner; 57d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 58d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mBindButton; 59d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mUnbindButton; 60d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private TextView mBoundAdapterTextView; 61d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mStartSyncButton; 62d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mCancelSyncButton; 63d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private TextView mStatusTextView; 64d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Object[] mSyncAdapters; 65d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private SyncAdaptersCache mSyncAdaptersCache; 66d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private final Object mSyncAdaptersLock = new Object(); 67d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 68d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final int DIALOG_ID_PICK_ACCOUNT = 1; 69d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private ListView mAccountPickerView = null; 70d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 71d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana @Override 72d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected void onCreate(Bundle savedInstanceState) { 73d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana super.onCreate(savedInstanceState); 74d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache = new SyncAdaptersCache(this); 75d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana setContentView(R.layout.sync_adapter_driver); 76d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 77d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapterSpinner = (Spinner) findViewById(R.id.sync_adapters_spinner); 78d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBindButton = (Button) findViewById(R.id.bind_button); 79d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mUnbindButton = (Button) findViewById(R.id.unbind_button); 80d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView = (TextView) findViewById(R.id.bound_adapter_text_view); 81d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 82d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStartSyncButton = (Button) findViewById(R.id.start_sync_button); 83d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mCancelSyncButton = (Button) findViewById(R.id.cancel_sync_button); 84d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 85d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView = (TextView) findViewById(R.id.status_text_view); 86d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 87d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSyncAdapters(); 88cf229bb013317db77034980c212ab07bea260261Fred Quintana mSyncAdaptersCache.setListener(this, null /* Handler */); 89d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 90d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 91d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected void onDestroy() { 92d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache.close(); 93d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana super.onDestroy(); 94d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 95d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 96d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private void getSyncAdapters() { 97d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> all = 98d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache.getAllServices(); 99d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mSyncAdaptersLock) { 100d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters = new Object[all.size()]; 101d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana String[] names = new String[mSyncAdapters.length]; 102d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana int i = 0; 103d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> item : all) { 104d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters[i] = item; 105d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana names[i] = item.type.authority + " - " + item.type.accountType; 106d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana i++; 107d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 108d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 109d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ArrayAdapter<String> adapter = 110d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana new ArrayAdapter<String>(this, 111d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana R.layout.sync_adapter_item, names); 112d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapterSpinner.setAdapter(adapter); 113d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 114d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 115d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 116d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana void updateUi() { 117d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana boolean isBound; 118d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana boolean hasServiceConnection; 119d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 120d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana hasServiceConnection = mActiveServiceConnection != null; 121d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana isBound = hasServiceConnection && mActiveServiceConnection.mBoundSyncAdapter != null; 122d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 123d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStartSyncButton.setEnabled(isBound); 124d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mCancelSyncButton.setEnabled(isBound); 125d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBindButton.setEnabled(!hasServiceConnection); 126d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mUnbindButton.setEnabled(hasServiceConnection); 127d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 128d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 129d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void startSyncSelected(View view) { 130d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 131d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 132d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 133d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 134d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 135d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 136d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 137d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana removeDialog(DIALOG_ID_PICK_ACCOUNT); 138d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 139d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView = (ListView) LayoutInflater.from(this).inflate( 140d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana R.layout.account_list_view, null); 141d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView.setOnItemClickListener(this); 142d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Account accounts[] = AccountManager.get(this).getAccountsByType( 143d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.accountType); 144d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana String[] accountNames = new String[accounts.length]; 145d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana for (int i = 0; i < accounts.length; i++) { 146d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana accountNames[i] = accounts[i].name; 147d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 148d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ArrayAdapter<String> adapter = 149d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana new ArrayAdapter<String>(SyncAdapterDriver.this, 150d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana android.R.layout.simple_list_item_1, accountNames); 151d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView.setAdapter(adapter); 152d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 153d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana showDialog(DIALOG_ID_PICK_ACCOUNT); 154d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 155d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 156d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 157d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 158d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 159d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private void startSync(String accountName) { 160d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 161d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 162d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 163d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 164d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 165d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 166d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 167d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 168d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 169d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_starting_sync_format, accountName)); 170d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Account account = new Account(accountName, 171d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.accountType); 172d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter.startSync(mActiveServiceConnection, 173d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.authority, 174d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana account, new Bundle()); 175d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (RemoteException e) { 176d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 177d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_remote_exception_while_starting_sync)); 178d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 179d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 180d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 181d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 182d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 183d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 184d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void cancelSync(View view) { 185d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 186d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 187d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 188d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 189d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 190d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 191d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 192d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 193d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_canceled_sync)); 194d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter.cancelSync(mActiveServiceConnection); 195d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (RemoteException e) { 196d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 197d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_remote_exception_while_canceling_sync)); 198d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 199d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 200d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 201d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 202d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 203d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 204cf229bb013317db77034980c212ab07bea260261Fred Quintana public void onServiceChanged(SyncAdapterType type, boolean removed) { 205d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSyncAdapters(); 206d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 207d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 208d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana @Override 209d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected Dialog onCreateDialog(final int id) { 210d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (id == DIALOG_ID_PICK_ACCOUNT) { 211d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana AlertDialog.Builder builder = new AlertDialog.Builder(this); 212d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setMessage(R.string.select_account_to_sync); 213d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setInverseBackgroundForced(true); 214d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setView(mAccountPickerView); 215d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return builder.create(); 216d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 217d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return super.onCreateDialog(id); 218d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 219d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 220d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 221d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana TextView item = (TextView) view; 222d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String accountName = item.getText().toString(); 223d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana dismissDialog(DIALOG_ID_PICK_ACCOUNT); 224d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana startSync(accountName); 225d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 226d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 227d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private class MyServiceConnection extends ISyncContext.Stub implements ServiceConnection { 228d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private volatile ISyncAdapter mBoundSyncAdapter; 229d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final RegisteredServicesCache.ServiceInfo<SyncAdapterType> mSyncAdapter; 230d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 231d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public MyServiceConnection( 232d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter) { 233d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapter = syncAdapter; 234d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 235d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 236d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onServiceConnected(ComponentName name, IBinder service) { 237d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundSyncAdapter = ISyncAdapter.Stub.asInterface(service); 238d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final SyncAdapterType type = mActiveServiceConnection.mSyncAdapter.type; 239d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_connected_format, 240d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana type.authority, type.accountType)); 241d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 242d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 243d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 244d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onServiceDisconnected(ComponentName name) { 245d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_not_connected)); 246d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundSyncAdapter = null; 247d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 248d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 249d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 250d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void sendHeartbeat() { 251d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana runOnUiThread(new Runnable() { 252d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void run() { 253d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana uiThreadSendHeartbeat(); 254d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 255d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana }); 256d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 257d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 258d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void uiThreadSendHeartbeat() { 259d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_received_heartbeat)); 260d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 261d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 262d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void uiThreadOnFinished(SyncResult result) { 263d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (result.hasError()) { 264d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 265d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_sync_failed_format, result.toString())); 266d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } else { 267d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 268d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_sync_succeeded_format, result.toString())); 269d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 270d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 271d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 272d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onFinished(final SyncResult result) throws RemoteException { 273d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana runOnUiThread(new Runnable() { 274d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void run() { 275d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana uiThreadOnFinished(result); 276d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 277d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana }); 278d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 279d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 280d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 281d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final Object mServiceConnectionLock = new Object(); 282d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana MyServiceConnection mActiveServiceConnection; 283d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 284d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void initiateBind(View view) { 285d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 286d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 287d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_already_bound)); 288d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 289d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 290d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 291d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter = 292d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSelectedSyncAdapter(); 293d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter == null) { 294d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_sync_adapter_not_selected)); 295d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 296d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 297d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 298d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = new MyServiceConnection(syncAdapter); 299d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 300d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Intent intent = new Intent(); 301d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.setAction("android.content.SyncAdapter"); 302d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.setComponent(syncAdapter.componentName); 303d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.putExtra(Intent.EXTRA_CLIENT_LABEL, 304d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.string.sync_binding_label); 305d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 306d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana this, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0)); 307d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (!bindService(intent, mActiveServiceConnection, Context.BIND_AUTO_CREATE)) { 308d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_bind_failed)); 309d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = null; 310d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 311d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 312d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_waiting_for_connection)); 313d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 314d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 315d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 316d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 317d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void initiateUnbind(View view) { 318d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 319d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection == null) { 320d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 321d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 322d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(""); 323d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana unbindService(mActiveServiceConnection); 324d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = null; 325d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 326d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 327d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 328d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 329d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private RegisteredServicesCache.ServiceInfo<SyncAdapterType> getSelectedSyncAdapter() { 330d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mSyncAdaptersLock) { 331d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final int position = mSyncAdapterSpinner.getSelectedItemPosition(); 332d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (position == AdapterView.INVALID_POSITION) { 333d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 334d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 335d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 336d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana //noinspection unchecked 337d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return (RegisteredServicesCache.ServiceInfo<SyncAdapterType>) 338d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters[position]; 339d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (Exception e) { 340d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 341d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 342d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 343d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 344d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 345d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana static class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> { 346d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String SERVICE_INTERFACE = "android.content.SyncAdapter"; 347d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String SERVICE_META_DATA = "android.content.SyncAdapter"; 348d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String ATTRIBUTES_NAME = "sync-adapter"; 349d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 350d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana SyncAdaptersCache(Context context) { 351cf229bb013317db77034980c212ab07bea260261Fred Quintana super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, null); 352d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 353d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 35482ace4a0d750e377953141eeff84eb6c72655152Dianne Hackborn public SyncAdapterType parseServiceAttributes(Resources res, 35582ace4a0d750e377953141eeff84eb6c72655152Dianne Hackborn String packageName, AttributeSet attrs) { 35682ace4a0d750e377953141eeff84eb6c72655152Dianne Hackborn TypedArray sa = res.obtainAttributes(attrs, 357d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter); 358d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 359d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String authority = 360d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority); 361d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String accountType = 362d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType); 363d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (authority == null || accountType == null) { 364d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 365d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 366d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final boolean userVisible = sa.getBoolean( 367d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter_userVisible, true); 368d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final boolean supportsUploading = sa.getBoolean( 369d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter_supportsUploading, true); 370b751cd535f8b81bf45d765c1f9232e6d05e2cfd3Fred Quintana final boolean isAlwaysSyncable = sa.getBoolean( 371b751cd535f8b81bf45d765c1f9232e6d05e2cfd3Fred Quintana com.android.internal.R.styleable.SyncAdapter_isAlwaysSyncable, false); 372b751cd535f8b81bf45d765c1f9232e6d05e2cfd3Fred Quintana final boolean allowParallelSyncs = sa.getBoolean( 373b751cd535f8b81bf45d765c1f9232e6d05e2cfd3Fred Quintana com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs, false); 374bcc1cb9fc01b0acedcf7954344940df7c55fdf53Fred Quintana final String settingsActivity = 375bcc1cb9fc01b0acedcf7954344940df7c55fdf53Fred Quintana sa.getString(com.android.internal.R.styleable 376bcc1cb9fc01b0acedcf7954344940df7c55fdf53Fred Quintana .SyncAdapter_settingsActivity); 377b751cd535f8b81bf45d765c1f9232e6d05e2cfd3Fred Quintana return new SyncAdapterType(authority, accountType, userVisible, supportsUploading, 378bcc1cb9fc01b0acedcf7954344940df7c55fdf53Fred Quintana isAlwaysSyncable, allowParallelSyncs, settingsActivity); 379d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } finally { 380d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.recycle(); 381d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 382d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 383d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 384d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana} 385