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