MailboxFinder.java revision ec15f2356e47d621584cc3fc84c9c02557e0a0df
1/* 2 * Copyright (C) 2010 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.email.activity; 18 19import com.android.email.Controller; 20import com.android.email.ControllerResultUiThreadWrapper; 21import com.android.email.Email; 22import com.android.email.Utility; 23import com.android.email.mail.MessagingException; 24import com.android.email.provider.EmailContent.Account; 25import com.android.email.provider.EmailContent.AccountColumns; 26import com.android.email.provider.EmailContent.Mailbox; 27 28import android.content.ContentUris; 29import android.content.Context; 30import android.database.Cursor; 31import android.os.AsyncTask; 32import android.os.Handler; 33import android.util.Log; 34 35/** 36 * A class that finds a mailbox ID by account ID and mailbox type. 37 * 38 * If an account doesn't have a mailbox of a specified type, it refreshes the mailbox list and 39 * try looking for again. 40 */ 41public class MailboxFinder { 42 private final Context mContext; 43 private final Controller mController; 44 private final Controller.Result mControllerResults; 45 46 private final long mAccountId; 47 private final int mMailboxType; 48 private final Callback mCallback; 49 50 private FindMailboxTask mTask; 51 52 /** 53 * Callback for results. 54 */ 55 public interface Callback { 56 public void onAccountNotFound(); 57 public void onMailboxNotFound(long accountId); 58 public void onAccountSecurityHold(long accountId); 59 public void onMailboxFound(long accountId, long mailboxId); 60 } 61 62 /** 63 * Creates an instance for {@code accountId} and {@code mailboxType}. (But won't start yet) 64 * 65 * Must be called on the UI thread. 66 */ 67 public MailboxFinder(Context context, long accountId, int mailboxType, Callback callback) { 68 if (accountId == -1) { 69 throw new UnsupportedOperationException(); 70 } 71 mContext = context.getApplicationContext(); 72 mController = Controller.getInstance(context); 73 mAccountId = accountId; 74 mMailboxType = mailboxType; 75 mCallback = callback; 76 mControllerResults = new ControllerResultUiThreadWrapper<ControllerResults>( 77 new Handler(), new ControllerResults()); 78 mController.addResultCallback(mControllerResults); 79 } 80 81 /** 82 * Start looking up. 83 * 84 * Must be called on the UI thread. 85 */ 86 public void startLookup() { 87 stop(); 88 mTask = new FindMailboxTask(true); 89 mTask.execute(); 90 } 91 92 /** 93 * Stop the running worker task, if exists. 94 */ 95 public void stop() { 96 Utility.cancelTaskInterrupt(mTask); 97 mTask = null; 98 } 99 100 /** 101 * Stop the running task, if exists, and clean up internal resources. (MUST be called.) 102 */ 103 public void close() { 104 mController.removeResultCallback(mControllerResults); 105 stop(); 106 } 107 108 private class ControllerResults extends Controller.Result { 109 @Override 110 public void updateMailboxListCallback(MessagingException result, long accountId, 111 int progress) { 112 if (result != null) { 113 // Error while updating the mailbox list. Notify the UI... 114 mCallback.onMailboxNotFound(mAccountId); 115 } else { 116 // Messagebox list updated, look for mailbox again... 117 if (progress == 100 && accountId == mAccountId) { 118 mTask = new FindMailboxTask(false); 119 mTask.execute(); 120 } 121 } 122 } 123 } 124 125 /** 126 * Async task for finding a single mailbox by type. If a mailbox of a type is not found, 127 * and {@code okToRecurse} is true, we update the mailbox list and try looking again. 128 */ 129 private class FindMailboxTask extends AsyncTask<Void, Void, Long> { 130 private final boolean mOkToRecurse; 131 132 private static final int RESULT_MAILBOX_FOUND = 0; 133 private static final int RESULT_ACCOUNT_SECURITY_HOLD = 1; 134 private static final int RESULT_ACCOUNT_NOT_FOUND = 2; 135 private static final int RESULT_MAILBOX_NOT_FOUND = 3; 136 private static final int RESULT_START_NETWORK_LOOK_UP = 4; 137 138 private int mResult = -1; 139 140 /** 141 * Special constructor to cache some local info 142 */ 143 public FindMailboxTask(boolean okToRecurse) { 144 mOkToRecurse = okToRecurse; 145 } 146 147 @Override 148 protected Long doInBackground(Void... params) { 149 // Quick check that account is not in security hold 150 if (Account.isSecurityHold(mContext, mAccountId)) { 151 mResult = RESULT_ACCOUNT_SECURITY_HOLD; 152 return Mailbox.NO_MAILBOX; 153 } 154 155 // See if we can find the requested mailbox in the DB. 156 long mailboxId = Mailbox.findMailboxOfType(mContext, mAccountId, mMailboxType); 157 if (mailboxId != Mailbox.NO_MAILBOX) { 158 mResult = RESULT_MAILBOX_FOUND; 159 return mailboxId; // Found 160 } 161 162 // Mailbox not found. Does the account really exists? 163 final boolean accountExists = Account.isValidId(mContext, mAccountId); 164 if (accountExists) { 165 if (mOkToRecurse) { 166 // launch network lookup 167 mResult = RESULT_START_NETWORK_LOOK_UP; 168 } else { 169 mResult = RESULT_MAILBOX_NOT_FOUND; 170 } 171 } else { 172 mResult = RESULT_ACCOUNT_NOT_FOUND; 173 } 174 return Mailbox.NO_MAILBOX; 175 } 176 177 @Override 178 protected void onPostExecute(Long mailboxId) { 179 Log.w(Email.LOG_TAG, "" + isCancelled() + " " + mResult); 180 if (isCancelled()) { 181 return; 182 } 183 switch (mResult) { 184 case RESULT_ACCOUNT_SECURITY_HOLD: 185 Log.w(Email.LOG_TAG, "Account security hold."); 186 mCallback.onAccountSecurityHold(mAccountId); 187 return; 188 case RESULT_ACCOUNT_NOT_FOUND: 189 Log.w(Email.LOG_TAG, "Account not found."); 190 mCallback.onAccountNotFound(); 191 return; 192 case RESULT_MAILBOX_NOT_FOUND: 193 Log.w(Email.LOG_TAG, "Mailbox not found."); 194 mCallback.onMailboxNotFound(mAccountId); 195 return; 196 case RESULT_START_NETWORK_LOOK_UP: 197 // Not found locally. Let's sync the mailbox list... 198 Log.i(Email.LOG_TAG, "Mailbox not found locally. Starting network lookup."); 199 mController.updateMailboxList(mAccountId); 200 return; 201 case RESULT_MAILBOX_FOUND: 202 mCallback.onMailboxFound(mAccountId, mailboxId); 203 return; 204 default: 205 throw new RuntimeException(); 206 } 207 } 208 } 209 210 /* package */ Controller.Result getControllerResultsForTest() { 211 return mControllerResults; 212 } 213} 214