FillCallLogTestActivity.java revision e0b2f1e2d01d1ac52ba207dc7ce76971d853298e
1/* 2 * Copyright (C) 2011 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.contacts.tests.calllog; 18 19import android.app.Activity; 20import android.app.LoaderManager; 21import android.content.ContentProviderClient; 22import android.content.ContentValues; 23import android.content.CursorLoader; 24import android.content.Loader; 25import android.database.Cursor; 26import android.os.AsyncTask; 27import android.os.Bundle; 28import android.os.RemoteException; 29import android.provider.CallLog.Calls; 30import android.util.Log; 31import android.view.View; 32import android.widget.Button; 33import android.widget.CheckBox; 34import android.widget.ProgressBar; 35import android.widget.TextView; 36import android.widget.Toast; 37 38import com.android.contacts.tests.R; 39 40import java.util.Random; 41 42/** 43 * Activity to add entries to the call log for testing. 44 */ 45public class FillCallLogTestActivity extends Activity { 46 private static final String TAG = "FillCallLogTestActivity"; 47 /** Identifier of the loader for querying the call log. */ 48 private static final int CALLLOG_LOADER_ID = 1; 49 50 private static final Random RNG = new Random(); 51 private static final int[] CALL_TYPES = new int[] { 52 Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE, Calls.MISSED_TYPE, 53 }; 54 55 private TextView mNumberTextView; 56 private Button mAddButton; 57 private ProgressBar mProgressBar; 58 private CheckBox mUseRandomNumbers; 59 60 @Override 61 protected void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 setContentView(R.layout.fill_call_log_test); 64 mNumberTextView = (TextView) findViewById(R.id.number); 65 mAddButton = (Button) findViewById(R.id.add); 66 mProgressBar = (ProgressBar) findViewById(R.id.progress); 67 mUseRandomNumbers = (CheckBox) findViewById(R.id.use_random_numbers); 68 69 mAddButton.setOnClickListener(new View.OnClickListener(){ 70 @Override 71 public void onClick(View v) { 72 int count; 73 try { 74 count = Integer.parseInt(mNumberTextView.getText().toString()); 75 if (count > 100) { 76 throw new RuntimeException("Number too large. Max=100"); 77 } 78 } catch (RuntimeException e) { 79 Toast.makeText(FillCallLogTestActivity.this, e.toString(), Toast.LENGTH_LONG) 80 .show(); 81 return; 82 } 83 addEntriesToCallLog(count, mUseRandomNumbers.isChecked()); 84 mNumberTextView.setEnabled(false); 85 mAddButton.setEnabled(false); 86 mProgressBar.setProgress(0); 87 mProgressBar.setMax(count); 88 mProgressBar.setVisibility(View.VISIBLE); 89 } 90 }); 91 } 92 93 /** 94 * Adds a number of entries to the call log. The content of the entries is based on existing 95 * entries. 96 * 97 * @param count the number of entries to add 98 */ 99 private void addEntriesToCallLog(final int count, boolean useRandomNumbers) { 100 if (useRandomNumbers) { 101 addRandomNumbers(count); 102 } else { 103 getLoaderManager().initLoader(CALLLOG_LOADER_ID, null, 104 new CallLogLoaderListener(count)); 105 } 106 } 107 108 /** 109 * Calls when the insertion has completed. 110 * 111 * @param message the message to show in a toast to the user 112 */ 113 private void insertCompleted(String message) { 114 // Hide the progress bar. 115 mProgressBar.setVisibility(View.GONE); 116 // Re-enable the add button. 117 mNumberTextView.setEnabled(true); 118 mAddButton.setEnabled(true); 119 mNumberTextView.setText(""); 120 Toast.makeText(this, message, Toast.LENGTH_LONG).show(); 121 } 122 123 124 /** 125 * Creates a {@link ContentValues} object containing values corresponding to the given cursor. 126 * 127 * @param cursor the cursor from which to get the values 128 * @return a newly created content values object 129 */ 130 private ContentValues createContentValuesFromCursor(Cursor cursor) { 131 ContentValues values = new ContentValues(); 132 for (int column = 0; column < cursor.getColumnCount(); 133 ++column) { 134 String name = cursor.getColumnName(column); 135 switch (cursor.getType(column)) { 136 case Cursor.FIELD_TYPE_STRING: 137 values.put(name, cursor.getString(column)); 138 break; 139 case Cursor.FIELD_TYPE_INTEGER: 140 values.put(name, cursor.getLong(column)); 141 break; 142 case Cursor.FIELD_TYPE_FLOAT: 143 values.put(name, cursor.getDouble(column)); 144 break; 145 case Cursor.FIELD_TYPE_BLOB: 146 values.put(name, cursor.getBlob(column)); 147 break; 148 case Cursor.FIELD_TYPE_NULL: 149 values.putNull(name); 150 break; 151 default: 152 Log.d(TAG, "Invalid value in cursor: " + cursor.getType(column)); 153 break; 154 } 155 } 156 return values; 157 } 158 159 private void addRandomNumbers(int count) { 160 ContentValues[] values = new ContentValues[count]; 161 for (int i = 0; i < count; i++) { 162 values[i] = new ContentValues(); 163 values[i].put(Calls.NUMBER, generateRandomNumber()); 164 values[i].put(Calls.DATE, System.currentTimeMillis()); // Will be randomized later 165 values[i].put(Calls.DURATION, 1); // Will be overwritten later 166 } 167 new AsyncCallLogInserter(values).execute(new Void[0]); 168 } 169 170 private static String generateRandomNumber() { 171 return String.format("5%09d", RNG.nextInt(1000000000)); 172 } 173 174 /** Invokes {@link AsyncCallLogInserter} when the call log has loaded. */ 175 private final class CallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 176 /** The number of items to insert when done. */ 177 private final int mCount; 178 179 private CallLogLoaderListener(int count) { 180 mCount = count; 181 } 182 183 @Override 184 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 185 Log.d(TAG, "onCreateLoader"); 186 return new CursorLoader(FillCallLogTestActivity.this, Calls.CONTENT_URI, 187 null, null, null, null); 188 } 189 190 @Override 191 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 192 try { 193 Log.d(TAG, "onLoadFinished"); 194 195 if (data.getCount() == 0) { 196 // If there are no entries in the call log, we cannot generate new ones. 197 insertCompleted(getString(R.string.noLogEntriesToast)); 198 return; 199 } 200 201 data.moveToPosition(-1); 202 203 ContentValues[] values = new ContentValues[mCount]; 204 for (int index = 0; index < mCount; ++index) { 205 if (!data.moveToNext()) { 206 data.moveToFirst(); 207 } 208 values[index] = createContentValuesFromCursor(data); 209 } 210 new AsyncCallLogInserter(values).execute(new Void[0]); 211 } finally { 212 // This is a one shot loader. 213 getLoaderManager().destroyLoader(CALLLOG_LOADER_ID); 214 } 215 } 216 217 @Override 218 public void onLoaderReset(Loader<Cursor> loader) {} 219 } 220 221 /** Inserts a given number of entries in the call log based on the values given. */ 222 private final class AsyncCallLogInserter extends AsyncTask<Void, Integer, Integer> { 223 /** The number of items to insert. */ 224 private final ContentValues[] mValues; 225 226 public AsyncCallLogInserter(ContentValues[] values) { 227 mValues = values; 228 } 229 230 @Override 231 protected Integer doInBackground(Void... params) { 232 Log.d(TAG, "doInBackground"); 233 return insertIntoCallLog(); 234 } 235 236 @Override 237 protected void onProgressUpdate(Integer... values) { 238 Log.d(TAG, "onProgressUpdate"); 239 updateCount(values[0]); 240 } 241 242 @Override 243 protected void onPostExecute(Integer count) { 244 Log.d(TAG, "onPostExecute"); 245 insertCompleted(getString(R.string.addedLogEntriesToast, count)); 246 } 247 248 /** 249 * Inserts a number of entries in the call log based on the given templates. 250 * 251 * @return the number of inserted entries 252 */ 253 private Integer insertIntoCallLog() { 254 int inserted = 0; 255 256 for (int index = 0; index < mValues.length; ++index) { 257 ContentValues values = mValues[index]; 258 // These should not be set. 259 values.putNull(Calls._ID); 260 // Add some randomness to the date. For each new entry being added, add an extra 261 // day to the maximum possible offset from the original. 262 values.put(Calls.DATE, 263 values.getAsLong(Calls.DATE) 264 - RNG.nextInt(24 * 60 * 60 * (index + 1)) * 1000L); 265 // Add some randomness to the duration. 266 if (values.getAsLong(Calls.DURATION) > 0) { 267 values.put(Calls.DURATION, RNG.nextInt(30 * 60 * 60 * 1000)); 268 } 269 270 // Overwrite type. 271 values.put(Calls.TYPE, CALL_TYPES[RNG.nextInt(CALL_TYPES.length)]); 272 273 // Clear cached columns. 274 values.putNull(Calls.CACHED_FORMATTED_NUMBER); 275 values.putNull(Calls.CACHED_LOOKUP_URI); 276 values.putNull(Calls.CACHED_MATCHED_NUMBER); 277 values.putNull(Calls.CACHED_NAME); 278 values.putNull(Calls.CACHED_NORMALIZED_NUMBER); 279 values.putNull(Calls.CACHED_NUMBER_LABEL); 280 values.putNull(Calls.CACHED_NUMBER_TYPE); 281 values.putNull(Calls.CACHED_PHOTO_ID); 282 283 // Insert into the call log the newly generated entry. 284 ContentProviderClient contentProvider = 285 getContentResolver().acquireContentProviderClient( 286 Calls.CONTENT_URI); 287 try { 288 Log.d(TAG, "adding entry to call log"); 289 contentProvider.insert(Calls.CONTENT_URI, values); 290 ++inserted; 291 this.publishProgress(inserted); 292 } catch (RemoteException e) { 293 Log.d(TAG, "insert failed", e); 294 } 295 } 296 return inserted; 297 } 298 } 299 300 /** 301 * Updates the count shown to the user corresponding to the number of entries added. 302 * 303 * @param count the number of entries inserted so far 304 */ 305 public void updateCount(Integer count) { 306 mProgressBar.setProgress(count); 307 } 308} 309