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