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 
17 package com.android.providers.calendar;
18 
19 import android.app.ListActivity;
20 import android.content.ContentResolver;
21 import android.database.Cursor;
22 import android.os.AsyncTask;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.provider.CalendarContract;
26 import android.widget.ListAdapter;
27 import android.widget.SimpleAdapter;
28 import android.view.Window;
29 
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.List;
33 import 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  */
41 public 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
onPreExecute()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
doInBackground(Void... params)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
onPostExecute(List<Map<String, String>> items)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
onCreate(Bundle savedInstanceState)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      */
addItem(List<Map<String, String>> items, String title, String text)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