143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani/*
243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * Copyright (C) 2008 The Android Open Source Project
343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani *
443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * you may not use this file except in compliance with the License.
643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * You may obtain a copy of the License at
743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani *
843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani *
1043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * Unless required by applicable law or agreed to in writing, software
1143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
1243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * See the License for the specific language governing permissions and
1443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani * limitations under the License.
1543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani */
1643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
1743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasanipackage com.android.settings.accounts;
1843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
1943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport java.util.ArrayList;
20d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasaniimport java.util.Date;
2143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport java.util.HashMap;
2243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport java.util.Map;
2343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
2443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport com.android.settings.SettingsPreferenceFragment;
2543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport com.google.android.collect.Maps;
2643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
2743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.accounts.Account;
2843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.accounts.AccountManager;
2943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.accounts.AuthenticatorDescription;
3043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.accounts.OnAccountsUpdateListener;
31d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasaniimport android.app.Activity;
3243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.content.ContentResolver;
3343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.content.Context;
3443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.content.SyncAdapterType;
3543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.content.SyncStatusObserver;
3643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.content.pm.PackageManager;
37d26321eecb481528c5e54a608f2f3c4cc26d8a77Brian Carlstromimport android.content.res.Resources;
3843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.graphics.drawable.Drawable;
3943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.os.Bundle;
4043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.os.Handler;
4143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.preference.PreferenceActivity;
4243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.preference.PreferenceScreen;
43d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasaniimport android.text.format.DateFormat;
4443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniimport android.util.Log;
4543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
4643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasaniclass AccountPreferenceBase extends SettingsPreferenceFragment
4743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        implements OnAccountsUpdateListener {
4843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
4943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    protected static final String TAG = "AccountSettings";
5043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public static final String AUTHORITIES_FILTER_KEY = "authorities";
5143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types";
5243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    private final Handler mHandler = new Handler();
5343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    private Object mStatusChangeListenerHandle;
5443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
55d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    private AuthenticatorHelper mAuthenticatorHelper = new AuthenticatorHelper();
56d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    private java.text.DateFormat mDateFormat;
57d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    private java.text.DateFormat mTimeFormat;
5843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
5943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    /**
6043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * Overload to handle account updates.
6143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     */
6243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public void onAccountsUpdated(Account[] accounts) {
6343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
6443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
6543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
6643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    /**
6743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * Overload to handle authenticator description updates
6843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     */
6943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    protected void onAuthDescriptionsUpdated() {
7043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
7143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
7243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
7343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    /**
7443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * Overload to handle sync state updates.
7543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     */
7643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    protected void onSyncStateUpdated() {
7743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
7843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
7943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
8043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    @Override
81d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    public void onActivityCreated(Bundle savedInstanceState) {
82d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        super.onActivityCreated(savedInstanceState);
83d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
84d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        final Activity activity = getActivity();
85d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
86d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        mDateFormat = DateFormat.getDateFormat(activity);
87d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        mTimeFormat = DateFormat.getTimeFormat(activity);
88d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    }
89d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
90d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    @Override
9143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public void onResume() {
9243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        super.onResume();
9343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        mStatusChangeListenerHandle = ContentResolver.addStatusChangeListener(
9443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE
9543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                | ContentResolver.SYNC_OBSERVER_TYPE_STATUS
9643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                | ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
9743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                mSyncStatusObserver);
9843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        onSyncStateUpdated();
9943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
10043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
10143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    @Override
10243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public void onPause() {
10343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        super.onPause();
10443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        ContentResolver.removeStatusChangeListener(mStatusChangeListenerHandle);
10543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
10643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
10743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() {
10843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        public void onStatusChanged(int which) {
10943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            mHandler.post(new Runnable() {
11043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                public void run() {
11143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                    onSyncStateUpdated();
11243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                }
11343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            });
11443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        }
11543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    };
11643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
11743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    public ArrayList<String> getAuthoritiesForAccountType(String type) {
11843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        if (mAccountTypeToAuthorities == null) {
11943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            mAccountTypeToAuthorities = Maps.newHashMap();
12043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
12143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            for (int i = 0, n = syncAdapters.length; i < n; i++) {
12243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                final SyncAdapterType sa = syncAdapters[i];
12343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
12443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                if (authorities == null) {
12543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                    authorities = new ArrayList<String>();
12643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                    mAccountTypeToAuthorities.put(sa.accountType, authorities);
12743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                }
12843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                if (Log.isLoggable(TAG, Log.VERBOSE)) {
129d26321eecb481528c5e54a608f2f3c4cc26d8a77Brian Carlstrom                    Log.d(TAG, "added authority " + sa.authority + " to accountType "
13043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                            + sa.accountType);
13143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                }
13243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                authorities.add(sa.authority);
13343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            }
13443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        }
13543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        return mAccountTypeToAuthorities.get(type);
13643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
13743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
13843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    /**
13943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * Gets the preferences.xml file associated with a particular account type.
14043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * @param accountType the type of account
14143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     * @return a PreferenceScreen inflated from accountPreferenceId.
14243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani     */
143d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    public PreferenceScreen addPreferencesForType(final String accountType,
144d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani            PreferenceScreen parent) {
14543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        PreferenceScreen prefs = null;
146d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        if (mAuthenticatorHelper.containsAccountType(accountType)) {
14743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            AuthenticatorDescription desc = null;
14843c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            try {
149d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                desc = mAuthenticatorHelper.getAccountTypeDescription(accountType);
15043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                if (desc != null && desc.accountPreferencesId != 0) {
15143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                    Context authContext = getActivity().createPackageContext(desc.packageName, 0);
15243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                    prefs = getPreferenceManager().inflateFromResource(authContext,
153d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani                            desc.accountPreferencesId, parent);
15443c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                }
15543c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            } catch (PackageManager.NameNotFoundException e) {
15643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
157d26321eecb481528c5e54a608f2f3c4cc26d8a77Brian Carlstrom            } catch (Resources.NotFoundException e) {
158d26321eecb481528c5e54a608f2f3c4cc26d8a77Brian Carlstrom                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
15943c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani            }
16043c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        }
16143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        return prefs;
16243c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
16343c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani
164d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    public void updateAuthDescriptions() {
165d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        mAuthenticatorHelper.updateAuthDescriptions(getActivity());
16643c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani        onAuthDescriptionsUpdated();
16743c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani    }
168d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
169d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    protected Drawable getDrawableForType(final String accountType) {
170d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        return mAuthenticatorHelper.getDrawableForType(getActivity(), accountType);
171d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    }
172d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
173d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    protected CharSequence getLabelForType(final String accountType) {
174d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        return mAuthenticatorHelper.getLabelForType(getActivity(), accountType);
175d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    }
176d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani
177d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    protected String formatSyncDate(Date date) {
178d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        // TODO: Switch to using DateUtils.formatDateTime
179d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani        return mDateFormat.format(date) + " " + mTimeFormat.format(date);
180d1ab82807aae63926b35f66080a1f7a75c00b95bAmith Yamasani    }
18143c697854c7e373fbc1dae8b7a5259a32de346b4Amith Yamasani}
182