1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.providers.calendar; 18 19import android.app.ListActivity; 20import android.content.ContentResolver; 21import android.database.Cursor; 22import android.os.AsyncTask; 23import android.os.Bundle; 24import android.os.Handler; 25import android.provider.CalendarContract; 26import android.widget.ListAdapter; 27import android.widget.SimpleAdapter; 28import android.view.Window; 29 30import java.util.ArrayList; 31import java.util.HashMap; 32import java.util.List; 33import java.util.Map; 34 35/** 36 * Displays info about all the user's calendars, for debugging. 37 * 38 * The info is displayed as a ListActivity, where each entry has the calendar name 39 * followed by information about the calendar. 40 */ 41public class CalendarDebug extends ListActivity { 42 private static final String[] CALENDARS_PROJECTION = new String[]{ 43 CalendarContract.Calendars._ID, 44 CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, 45 }; 46 private static final int INDEX_ID = 0; 47 private static final int INDEX_DISPLAY_NAME = 1; 48 49 private static final String[] EVENTS_PROJECTION = new String[]{ 50 CalendarContract.Events._ID, 51 }; 52 private static final String KEY_TITLE = "title"; 53 private static final String KEY_TEXT = "text"; 54 55 private ContentResolver mContentResolver; 56 private ListActivity mActivity; 57 58 /** 59 * Task to fetch info from the database and display as a ListActivity. 60 */ 61 private class FetchInfoTask extends AsyncTask<Void, Void, List<Map<String, String>>> { 62 /** 63 * Starts spinner while task is running. 64 * 65 * @see #onPostExecute 66 * @see #doInBackground 67 */ 68 @Override 69 protected void onPreExecute() { 70 setProgressBarIndeterminateVisibility(true); 71 } 72 73 /** 74 * Fetches debugging info from the database 75 * @param params Void 76 * @return a Map for each calendar 77 */ 78 @Override 79 protected List<Map<String, String>> doInBackground(Void... params) { 80 Cursor cursor = null; 81 // items is the list of items to display in the list. 82 List<Map<String, String>> items = new ArrayList<Map<String, String>>(); 83 try { 84 cursor = mContentResolver.query(CalendarContract.Calendars.CONTENT_URI, 85 CALENDARS_PROJECTION, 86 null, null /* selectionArgs */, 87 CalendarContract.Calendars.DEFAULT_SORT_ORDER); 88 if (cursor == null) { 89 addItem(items, mActivity.getString(R.string.calendar_info_error), ""); 90 } else { 91 while (cursor.moveToNext()) { 92 // Process each calendar 93 int id = cursor.getInt(INDEX_ID); 94 int eventCount = -1; 95 int dirtyCount = -1; 96 String displayName = cursor.getString(INDEX_DISPLAY_NAME); 97 98 // Compute number of events in the calendar 99 String where = CalendarContract.Events.CALENDAR_ID + "=" + id; 100 Cursor eventCursor = mContentResolver.query( 101 CalendarContract.Events.CONTENT_URI, EVENTS_PROJECTION, where, 102 null, null); 103 try { 104 eventCount = eventCursor.getCount(); 105 } finally { 106 eventCursor.close(); 107 } 108 109 // Compute number of dirty events in the calendar 110 String dirtyWhere = CalendarContract.Events.CALENDAR_ID + "=" + id 111 + " AND " + CalendarContract.Events.DIRTY + "=1"; 112 Cursor dirtyCursor = mContentResolver.query( 113 CalendarContract.Events.CONTENT_URI, EVENTS_PROJECTION, dirtyWhere, 114 null, null); 115 try { 116 dirtyCount = dirtyCursor.getCount(); 117 } finally { 118 dirtyCursor.close(); 119 } 120 121 // Format the output 122 String text; 123 if (dirtyCount == 0) { 124 text = mActivity.getString(R.string.calendar_info_events, 125 eventCount); 126 } else { 127 text = mActivity.getString(R.string.calendar_info_events_dirty, 128 eventCount, dirtyCount); 129 } 130 131 addItem(items, displayName, text); 132 } 133 } 134 } catch (Exception e) { 135 // Want to catch all exceptions. The point of this code is to debug 136 // when something bad is happening. 137 addItem(items, mActivity.getString(R.string.calendar_info_error), e.toString()); 138 } finally { 139 if (cursor != null) { 140 cursor.close(); 141 } 142 } 143 144 if (items.size() == 0) { 145 addItem(items, mActivity.getString(R.string.calendar_info_no_calendars), ""); 146 } 147 return items; 148 } 149 150 /** 151 * Runs on the UI thread to display the debugging info. 152 * 153 * @param items The info items to display. 154 * @see #onPreExecute 155 * @see #doInBackground 156 */ 157 @Override 158 protected void onPostExecute(List<Map<String, String>> items) { 159 setProgressBarIndeterminateVisibility(false); 160 ListAdapter adapter = new SimpleAdapter(mActivity, items, 161 android.R.layout.simple_list_item_2, new String[]{KEY_TITLE, KEY_TEXT}, 162 new int[]{android.R.id.text1, android.R.id.text2}); 163 164 // Bind to our new adapter. 165 setListAdapter(adapter); 166 } 167 } 168 169 @Override 170 protected void onCreate(Bundle savedInstanceState) { 171 super.onCreate(savedInstanceState); 172 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 173 mActivity = this; 174 mContentResolver = getContentResolver(); 175 getListView(); // Instantiate, for spinner 176 new FetchInfoTask().execute(); 177 178 } 179 180 /** 181 * Adds an item to the item map 182 * @param items The item map to update 183 * @param title Title of the item 184 * @param text Text of the item 185 */ 186 protected void addItem(List<Map<String, String>> items, String title, String text) { 187 Map<String, String> itemMap = new HashMap<String, String>(); 188 itemMap.put(KEY_TITLE, title); 189 itemMap.put(KEY_TEXT, text); 190 items.add(itemMap); 191 } 192} 193