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