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