SelectSyncedCalendarsMultiAccountAdapter.java revision 95e9538c2e504ea5528b07e3abdf54bb3d91c88a
12aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan/* 22aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Copyright (C) 2011 The Android Open Source Project 32aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 42aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 52aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * you may not use this file except in compliance with the License. 62aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * You may obtain a copy of the License at 72aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 82aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * http://www.apache.org/licenses/LICENSE-2.0 92aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 102aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Unless required by applicable law or agreed to in writing, software 112aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * distributed under the License is distributed on an "AS IS" BASIS, 122aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * See the License for the specific language governing permissions and 142aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * limitations under the License. 152aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan */ 162aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 172aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanpackage com.android.calendar.selectcalendars; 182aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 192aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.accounts.AccountManager; 202aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.accounts.AuthenticatorDescription; 2114d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport android.app.FragmentManager; 222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.AsyncQueryHandler; 232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.ContentResolver; 242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.ContentUris; 252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.ContentValues; 262aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.Context; 272aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.pm.PackageManager; 282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.database.Cursor; 292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.database.MatrixCursor; 3014d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport android.graphics.Rect; 312aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.net.Uri; 322aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.provider.CalendarContract.Calendars; 332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.text.TextUtils; 342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.util.Log; 352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.view.LayoutInflater; 3614d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport android.view.TouchDelegate; 372aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.view.View; 3814d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport android.view.View.OnClickListener; 392aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.view.ViewGroup; 402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.widget.CheckBox; 412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.widget.CursorTreeAdapter; 422aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.widget.TextView; 432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 4414d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport com.android.calendar.CalendarColorPickerDialog; 4514d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport com.android.calendar.R; 4614d76a209b38d1f1b9db35256880d40319e3e35eJames Kungimport com.android.calendar.Utils; 4714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 482aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport java.util.HashMap; 492aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport java.util.Iterator; 502aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport java.util.Map; 512aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 522aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanpublic class SelectSyncedCalendarsMultiAccountAdapter extends CursorTreeAdapter implements 532aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan View.OnClickListener { 542aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 552aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String TAG = "Calendar"; 562aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 572aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String IS_PRIMARY = "\"primary\""; 582aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String CALENDARS_ORDERBY = IS_PRIMARY + " DESC," 592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan + Calendars.CALENDAR_DISPLAY_NAME + " COLLATE NOCASE"; 602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String ACCOUNT_SELECTION = Calendars.ACCOUNT_NAME + "=?" 612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan + " AND " + Calendars.ACCOUNT_TYPE + "=?"; 622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private final LayoutInflater mInflater; 642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private final ContentResolver mResolver; 652aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private final SelectSyncedCalendarsMultiAccountActivity mActivity; 6614d76a209b38d1f1b9db35256880d40319e3e35eJames Kung private final FragmentManager mFragmentManager; 6714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung private final boolean mIsTablet; 6814d76a209b38d1f1b9db35256880d40319e3e35eJames Kung private CalendarColorPickerDialog mDialog; 692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private final View mView; 702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private final static Runnable mStopRefreshing = new Runnable() { 712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void run() { 722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mRefresh = false; 732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan }; 752aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private Map<String, AuthenticatorDescription> mTypeToAuthDescription 762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan = new HashMap<String, AuthenticatorDescription>(); 772aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected AuthenticatorDescription[] mAuthDescs; 782aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 792aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // These track changes to the synced state of calendars 802aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private Map<Long, Boolean> mCalendarChanges 812aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan = new HashMap<Long, Boolean>(); 822aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private Map<Long, Boolean> mCalendarInitialStates 832aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan = new HashMap<Long, Boolean>(); 842aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 8518431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein // Flag for when the cursors have all been closed to ensure no race condition with queries. 8618431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein private boolean mClosedCursorsFlag; 8718431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein 882aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // This is for keeping MatrixCursor copies so that we can requery in the background. 8918431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein private Map<String, Cursor> mChildrenCursors 902aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan = new HashMap<String, Cursor>(); 912aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 9218431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein private AsyncCalendarsUpdater mCalendarsUpdater; 932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // This is to keep our update tokens separate from other tokens. Since we cancel old updates 942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // when a new update comes in, we'd like to leave a token space that won't be canceled. 952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int MIN_UPDATE_TOKEN = 1000; 962aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static int mUpdateToken = MIN_UPDATE_TOKEN; 972aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // How long to wait between requeries of the calendars to see if anything has changed. 982aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int REFRESH_DELAY = 5000; 992aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // How long to keep refreshing for 1002aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int REFRESH_DURATION = 60000; 1012aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static boolean mRefresh = true; 1022aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1032aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static String mSyncedText; 1042aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static String mNotSyncedText; 1052aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1062aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // This is to keep track of whether or not multiple calendars have the same display name 1072aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static HashMap<String, Boolean> mIsDuplicateName = new HashMap<String, Boolean>(); 1082aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 10914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung private int mColorViewTouchAreaIncrease; 11014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 1112aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String[] PROJECTION = new String[] { 1122aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars._ID, 1132aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.ACCOUNT_NAME, 1142aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.OWNER_ACCOUNT, 1152aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.CALENDAR_DISPLAY_NAME, 1162aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.CALENDAR_COLOR, 1172aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.VISIBLE, 1182aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.SYNC_EVENTS, 1192aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY, 1202aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan }; 1212aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan //Keep these in sync with the projection 1222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int ID_COLUMN = 0; 1232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int ACCOUNT_COLUMN = 1; 1242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int OWNER_COLUMN = 2; 1252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int NAME_COLUMN = 3; 1262aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int COLOR_COLUMN = 4; 1272aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int SELECTED_COLUMN = 5; 1282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int SYNCED_COLUMN = 6; 1292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int PRIMARY_COLUMN = 7; 1302aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1312aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int TAG_ID_CALENDAR_ID = R.id.calendar; 1322aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final int TAG_ID_SYNC_CHECKBOX = R.id.sync; 1332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private class AsyncCalendarsUpdater extends AsyncQueryHandler { 1352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1362aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public AsyncCalendarsUpdater(ContentResolver cr) { 1372aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super(cr); 1382aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1392aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 1412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 1422aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(cursor == null) { 1432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return; 1442aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 14518431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein synchronized(mChildrenCursors) { 14618431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein if (mClosedCursorsFlag || (mActivity != null && mActivity.isFinishing())) { 14718431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein cursor.close(); 14818431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein return; 14918431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 15018431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 1512aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1522aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Cursor currentCursor = mChildrenCursors.get(cookie); 1532aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Check if the new cursor has the same content as our old cursor 1542aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (currentCursor != null) { 1552aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (Utils.compareCursors(currentCursor, cursor)) { 1562aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan cursor.close(); 1572aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return; 1582aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // If not then make a new matrix cursor for our Map 1612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan MatrixCursor newCursor = Utils.matrixCursorFromCursor(cursor); 1622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan cursor.close(); 1632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // And update our list of duplicated names 1642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Utils.checkForDuplicateNames(mIsDuplicateName, newCursor, NAME_COLUMN); 1652aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1662aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mChildrenCursors.put((String)cookie, newCursor); 1672aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan try { 1682aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setChildrenCursor(token, newCursor); 1692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } catch (NullPointerException e) { 1702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Log.w(TAG, "Adapter expired, try again on the next query: " + e); 1712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Clean up our old cursor if we had one. We have to do this after setting the new 1732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // cursor so that our view doesn't throw on an invalid cursor. 1742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (currentCursor != null) { 1752aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan currentCursor.close(); 1762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1772aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1782aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1792aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1802aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan /** 1812aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Method for changing the sync state when a calendar's button is pressed. 1822aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 1832aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * This gets called when the CheckBox for a calendar is clicked. It toggles 1842aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * the sync state for the associated calendar and saves a change of state to 1852aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * a hashmap. It also compares against the original value and removes any 1862aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * changes from the hashmap if this is back at its initial state. 1872aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan */ 1882aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void onClick(View v) { 1892aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan long id = (Long) v.getTag(TAG_ID_CALENDAR_ID); 1902aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan boolean newState; 1912aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan boolean initialState = mCalendarInitialStates.get(id); 1922aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (mCalendarChanges.containsKey(id)) { 1932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Negate to reflect the click 1942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan newState = !mCalendarChanges.get(id); 1952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } else { 1962aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Negate to reflect the click 1972aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan newState = !initialState; 1982aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1992aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2002aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (newState == initialState) { 2012aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarChanges.remove(id); 2022aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } else { 2032aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarChanges.put(id, newState); 2042aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2052aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2062aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ((CheckBox) v.getTag(TAG_ID_SYNC_CHECKBOX)).setChecked(newState); 2072aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setText(v, R.id.status, newState ? mSyncedText : mNotSyncedText); 2082aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2092aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2102aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public SelectSyncedCalendarsMultiAccountAdapter(Context context, Cursor acctsCursor, 2112aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan SelectSyncedCalendarsMultiAccountActivity act) { 2122aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super(acctsCursor, context); 2132aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mSyncedText = context.getString(R.string.synced); 2142aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mNotSyncedText = context.getString(R.string.not_synced); 2152aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2162aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2172aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mResolver = context.getContentResolver(); 2182aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mActivity = act; 21914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung mFragmentManager = act.getFragmentManager(); 22014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung mIsTablet = Utils.getConfigBool(context, R.bool.tablet_config); 22114d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 2222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (mCalendarsUpdater == null) { 2232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarsUpdater = new AsyncCalendarsUpdater(mResolver); 2242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2266fb869698103a0f897537fa7f4ebabe714db9d37Michael Chan if (acctsCursor == null || acctsCursor.getCount() == 0) { 2276fb869698103a0f897537fa7f4ebabe714db9d37Michael Chan Log.i(TAG, "SelectCalendarsAdapter: No accounts were returned!"); 2282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Collect proper description for account types 2302aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mAuthDescs = AccountManager.get(context).getAuthenticatorTypes(); 2312aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan for (int i = 0; i < mAuthDescs.length; i++) { 2322aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]); 2332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mView = mActivity.getExpandableListView(); 2352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mRefresh = true; 23618431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein mClosedCursorsFlag = false; 23714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 23814d76a209b38d1f1b9db35256880d40319e3e35eJames Kung mColorViewTouchAreaIncrease = context.getResources() 23914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung .getDimensionPixelSize(R.dimen.color_view_touch_area_increase); 2402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2422aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void startRefreshStopDelay() { 2432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mRefresh = true; 2442aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mView.postDelayed(mStopRefreshing, REFRESH_DURATION); 2452aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2462aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2472aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void cancelRefreshStopDelay() { 2482aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mView.removeCallbacks(mStopRefreshing); 2492aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2502aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2512aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan /* 2522aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Write back the changes that have been made. The sync code will pick up any changes and 2532aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * do updates on its own. 2542aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan */ 2552aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void doSaveAction() { 2562aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Cancel the previous operation 2572aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarsUpdater.cancelOperation(mUpdateToken); 2582aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mUpdateToken++; 2592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // This is to allow us to do queries and updates with the same AsyncQueryHandler without 2602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // accidently canceling queries. 2612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(mUpdateToken < MIN_UPDATE_TOKEN) { 2622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mUpdateToken = MIN_UPDATE_TOKEN; 2632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2652aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Iterator<Long> changeKeys = mCalendarChanges.keySet().iterator(); 2662aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan while (changeKeys.hasNext()) { 2672aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan long id = changeKeys.next(); 2682aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan boolean newSynced = mCalendarChanges.get(id); 2692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, id); 2712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ContentValues values = new ContentValues(); 2722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan values.put(Calendars.VISIBLE, newSynced ? 1 : 0); 2732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan values.put(Calendars.SYNC_EVENTS, newSynced ? 1 : 0); 2742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarsUpdater.startUpdate(mUpdateToken, id, uri, values, null, null); 2752aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2772aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2782aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static void setText(View view, int id, String text) { 2792aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (TextUtils.isEmpty(text)) { 2802aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return; 2812aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2822aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan TextView textView = (TextView) view.findViewById(id); 2832aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan textView.setText(text); 2842aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 2852aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 2862aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan /** 2872aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Gets the label associated with a particular account type. If none found, return null. 2882aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * @param accountType the type of account 2892aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * @return a CharSequence for the label or null if one cannot be found. 2902aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan */ 2912aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected CharSequence getLabelForType(final String accountType) { 2922aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan CharSequence label = null; 2932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (mTypeToAuthDescription.containsKey(accountType)) { 2942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan try { 2952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); 2962aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Context authContext = mActivity.createPackageContext(desc.packageName, 0); 2972aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan label = authContext.getResources().getText(desc.labelId); 2982aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } catch (PackageManager.NameNotFoundException e) { 2992aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Log.w(TAG, "No label for account type " + ", type " + accountType); 3002aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3012aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3022aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return label; 3032aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3042aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3052aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 3062aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) { 30714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung final long id = cursor.getLong(ID_COLUMN); 3082aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String name = cursor.getString(NAME_COLUMN); 3092aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String owner = cursor.getString(OWNER_COLUMN); 31014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung int color = Utils.getDisplayColorFromColor(cursor.getInt(COLOR_COLUMN)); 31114d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 31214d76a209b38d1f1b9db35256880d40319e3e35eJames Kung final View colorSquare = view.findViewById(R.id.color); 31314d76a209b38d1f1b9db35256880d40319e3e35eJames Kung colorSquare.setBackgroundColor(color); 31414d76a209b38d1f1b9db35256880d40319e3e35eJames Kung final View delegateParent = (View) colorSquare.getParent(); 31514d76a209b38d1f1b9db35256880d40319e3e35eJames Kung delegateParent.post(new Runnable() { 31614d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 31714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung @Override 31814d76a209b38d1f1b9db35256880d40319e3e35eJames Kung public void run() { 31914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung final Rect r = new Rect(); 32014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung colorSquare.getHitRect(r); 32114d76a209b38d1f1b9db35256880d40319e3e35eJames Kung r.top -= mColorViewTouchAreaIncrease; 32214d76a209b38d1f1b9db35256880d40319e3e35eJames Kung r.bottom += mColorViewTouchAreaIncrease; 32314d76a209b38d1f1b9db35256880d40319e3e35eJames Kung r.left -= mColorViewTouchAreaIncrease; 32414d76a209b38d1f1b9db35256880d40319e3e35eJames Kung r.right += mColorViewTouchAreaIncrease; 32514d76a209b38d1f1b9db35256880d40319e3e35eJames Kung delegateParent.setTouchDelegate(new TouchDelegate(r, colorSquare)); 32614d76a209b38d1f1b9db35256880d40319e3e35eJames Kung } 32714d76a209b38d1f1b9db35256880d40319e3e35eJames Kung }); 32814d76a209b38d1f1b9db35256880d40319e3e35eJames Kung colorSquare.setOnClickListener(new OnClickListener() { 32914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung 33014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung @Override 33114d76a209b38d1f1b9db35256880d40319e3e35eJames Kung public void onClick(View v) { 33214d76a209b38d1f1b9db35256880d40319e3e35eJames Kung if (mDialog == null) { 3338de796dfd3a1dad6cb386077e785d09fc02bec7bJames Kung mDialog = CalendarColorPickerDialog.newInstance(id, mIsTablet); 33414d76a209b38d1f1b9db35256880d40319e3e35eJames Kung } else { 33514d76a209b38d1f1b9db35256880d40319e3e35eJames Kung mDialog.setCalendarId(id); 33614d76a209b38d1f1b9db35256880d40319e3e35eJames Kung } 33795e9538c2e504ea5528b07e3abdf54bb3d91c88aJames Kung mFragmentManager.executePendingTransactions(); 33814d76a209b38d1f1b9db35256880d40319e3e35eJames Kung if (!mDialog.isAdded()) { 33914d76a209b38d1f1b9db35256880d40319e3e35eJames Kung mDialog.show(mFragmentManager, TAG); 34014d76a209b38d1f1b9db35256880d40319e3e35eJames Kung } 34114d76a209b38d1f1b9db35256880d40319e3e35eJames Kung } 34214d76a209b38d1f1b9db35256880d40319e3e35eJames Kung }); 3432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (mIsDuplicateName.containsKey(name) && mIsDuplicateName.get(name) && 3442aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan !name.equalsIgnoreCase(owner)) { 3452aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan name = new StringBuilder(name) 3462aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan .append(Utils.OPEN_EMAIL_MARKER) 3472aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan .append(owner) 3482aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan .append(Utils.CLOSE_EMAIL_MARKER) 3492aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan .toString(); 3502aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3512aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setText(view, R.id.calendar, name); 3522aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3532aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // First see if the user has already changed the state of this calendar 3542aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Boolean sync = mCalendarChanges.get(id); 3552aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (sync == null) { 3562aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan sync = cursor.getInt(SYNCED_COLUMN) == 1; 3572aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarInitialStates.put(id, sync); 3582aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan CheckBox button = (CheckBox) view.findViewById(R.id.sync); 3612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan button.setChecked(sync); 3622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setText(view, R.id.status, sync ? mSyncedText : mNotSyncedText); 3632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan view.setTag(TAG_ID_CALENDAR_ID, id); 3652aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan view.setTag(TAG_ID_SYNC_CHECKBOX, button); 3662aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan view.setOnClickListener(this); 3672aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3682aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 3702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) { 3712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int accountColumn = cursor.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME); 3722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int accountTypeColumn = cursor.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE); 3732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String account = cursor.getString(accountColumn); 3742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String accountType = cursor.getString(accountTypeColumn); 375953fb5d952c793a2514fd48abef8d8bcff7661dcSara Ting CharSequence accountLabel = getLabelForType(accountType); 3762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setText(view, R.id.account, account); 377953fb5d952c793a2514fd48abef8d8bcff7661dcSara Ting if (accountLabel != null) { 378953fb5d952c793a2514fd48abef8d8bcff7661dcSara Ting setText(view, R.id.account_type, accountLabel.toString()); 379953fb5d952c793a2514fd48abef8d8bcff7661dcSara Ting } 3802aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3812aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3822aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 3832aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected Cursor getChildrenCursor(Cursor groupCursor) { 3842aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int accountColumn = groupCursor.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME); 3852aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int accountTypeColumn = groupCursor.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE); 3862aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String account = groupCursor.getString(accountColumn); 3872aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String accountType = groupCursor.getString(accountTypeColumn); 3882aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan //Get all the calendars for just this account. 38965cf22bc9170c8aa6a26ef0bf91888a0ae1afaebMichael Chan Cursor childCursor = mChildrenCursors.get(accountType + "#" + account); 3902aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan new RefreshCalendars(groupCursor.getPosition(), account, accountType).run(); 3912aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return childCursor; 3922aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 3942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 3952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected View newChildView(Context context, Cursor cursor, boolean isLastChild, 3962aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ViewGroup parent) { 3972aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return mInflater.inflate(R.layout.calendar_sync_item, parent, false); 3982aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 3992aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 4002aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 4012aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected View newGroupView(Context context, Cursor cursor, boolean isExpanded, 4022aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ViewGroup parent) { 4032aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan return mInflater.inflate(R.layout.account_item, parent, false); 4042aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 4052aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 40618431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein public void closeChildrenCursors() { 40718431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein synchronized (mChildrenCursors) { 40818431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein for (String key : mChildrenCursors.keySet()) { 40918431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein Cursor cursor = mChildrenCursors.get(key); 41018431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein if (!cursor.isClosed()) { 41118431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein cursor.close(); 41218431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 41318431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 41418431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein mChildrenCursors.clear(); 41518431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein mClosedCursorsFlag = true; 41618431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 41718431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein } 41818431d19a22ad918aa4b6102649cc484929131bcSam Blitzstein 4192aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private class RefreshCalendars implements Runnable { 4202aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 4212aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int mToken; 4222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String mAccount; 4232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan String mAccountType; 4242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 42565cf22bc9170c8aa6a26ef0bf91888a0ae1afaebMichael Chan public RefreshCalendars(int token, String account, String accountType) { 4262aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mToken = token; 42765cf22bc9170c8aa6a26ef0bf91888a0ae1afaebMichael Chan mAccount = account; 4282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mAccountType = accountType; 4292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 4302aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 4312aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void run() { 4322aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarsUpdater.cancelOperation(mToken); 4332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Set up a refresh for some point in the future if we haven't stopped updates yet 4342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(mRefresh) { 4352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mView.postDelayed(new RefreshCalendars(mToken, mAccount, mAccountType), 4362aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan REFRESH_DELAY); 4372aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 4382aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCalendarsUpdater.startQuery(mToken, 43965cf22bc9170c8aa6a26ef0bf91888a0ae1afaebMichael Chan mAccountType + "#" + mAccount, 4402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.CONTENT_URI, PROJECTION, 4412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ACCOUNT_SELECTION, 4422aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan new String[] { mAccount, mAccountType } /*selectionArgs*/, 4432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan CALENDARS_ORDERBY); 4442aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 4452aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 4462aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan} 447