1 /* 2 * Copyright (C) 2008 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.email2.ui; 18 19 import android.content.ComponentName; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.UriMatcher; 24 import android.content.pm.PackageManager; 25 import android.database.Cursor; 26 import android.net.Uri; 27 import android.os.Bundle; 28 29 import com.android.email.NotificationController; 30 import com.android.email.Preferences; 31 import com.android.email.R; 32 import com.android.email.provider.EmailProvider; 33 import com.android.email.service.AttachmentService; 34 import com.android.email.service.EmailServiceUtils; 35 import com.android.emailcommon.Logging; 36 import com.android.emailcommon.TempDirectory; 37 import com.android.emailcommon.provider.Account; 38 import com.android.emailcommon.provider.EmailContent; 39 import com.android.emailcommon.provider.Mailbox; 40 import com.android.emailcommon.service.EmailServiceProxy; 41 import com.android.emailcommon.utility.EmailAsyncTask; 42 import com.android.emailcommon.utility.IntentUtilities; 43 import com.android.emailcommon.utility.Utility; 44 import com.android.mail.providers.Folder; 45 import com.android.mail.providers.UIProvider; 46 import com.android.mail.utils.LogTag; 47 import com.android.mail.utils.LogUtils; 48 import com.android.mail.utils.Utils; 49 50 public class MailActivityEmail extends com.android.mail.ui.MailActivity { 51 /** 52 * If this is enabled there will be additional logging information sent to 53 * LogUtils.d, including protocol dumps. 54 * 55 * This should only be used for logs that are useful for debbuging user problems, 56 * not for internal/development logs. 57 * 58 * This can be enabled by typing "debug" in the AccountFolderList activity. 59 * Changing the value to 'true' here will likely have no effect at all! 60 * 61 * TODO: rename this to sUserDebug, and rename LOGD below to DEBUG. 62 */ 63 public static boolean DEBUG; 64 65 public static final String LOG_TAG = LogTag.getLogTag(); 66 67 // Exchange debugging flags (passed to Exchange, when available, via EmailServiceProxy) 68 public static boolean DEBUG_EXCHANGE; 69 public static boolean DEBUG_VERBOSE; 70 public static boolean DEBUG_FILE; 71 72 private static final int MATCH_LEGACY_SHORTCUT_INTENT = 1; 73 /** 74 * A matcher for data URI's that specify conversation list info. 75 */ 76 private static final UriMatcher sUrlMatcher = new UriMatcher(UriMatcher.NO_MATCH); 77 static { 78 sUrlMatcher.addURI( 79 EmailProvider.LEGACY_AUTHORITY, "view/mailbox", MATCH_LEGACY_SHORTCUT_INTENT); 80 } 81 82 83 /** 84 * Asynchronous version of {@link #setServicesEnabledSync(Context)}. Use when calling from 85 * UI thread (or lifecycle entry points.) 86 */ 87 public static void setServicesEnabledAsync(final Context context) { 88 if (context.getResources().getBoolean(R.bool.enable_services)) { 89 EmailAsyncTask.runAsyncParallel(new Runnable() { 90 @Override 91 public void run() { 92 setServicesEnabledSync(context); 93 } 94 }); 95 } 96 } 97 98 /** 99 * Called throughout the application when the number of accounts has changed. This method 100 * enables or disables the Compose activity, the boot receiver and the service based on 101 * whether any accounts are configured. 102 * 103 * Blocking call - do not call from UI/lifecycle threads. 104 * 105 * @return true if there are any accounts configured. 106 */ 107 public static boolean setServicesEnabledSync(Context context) { 108 // Make sure we're initialized 109 EmailContent.init(context); 110 Cursor c = null; 111 try { 112 c = context.getContentResolver().query( 113 Account.CONTENT_URI, 114 Account.ID_PROJECTION, 115 null, null, null); 116 boolean enable = c != null && c.getCount() > 0; 117 setServicesEnabled(context, enable); 118 return enable; 119 } finally { 120 if (c != null) { 121 c.close(); 122 } 123 } 124 } 125 126 private static void setServicesEnabled(Context context, boolean enabled) { 127 PackageManager pm = context.getPackageManager(); 128 pm.setComponentEnabledSetting( 129 new ComponentName(context, AttachmentService.class), 130 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 131 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 132 PackageManager.DONT_KILL_APP); 133 134 // Start/stop the various services depending on whether there are any accounts 135 // TODO: Make sure that the AttachmentService responds to this request as it 136 // expects a particular set of data in the intents that it receives or it ignores. 137 startOrStopService(enabled, context, new Intent(context, AttachmentService.class)); 138 NotificationController.getInstance(context).watchForMessages(); 139 } 140 141 /** 142 * Starts or stops the service as necessary. 143 * @param enabled If {@code true}, the service will be started. Otherwise, it will be stopped. 144 * @param context The context to manage the service with. 145 * @param intent The intent of the service to be managed. 146 */ 147 private static void startOrStopService(boolean enabled, Context context, Intent intent) { 148 if (enabled) { 149 context.startService(intent); 150 } else { 151 context.stopService(intent); 152 } 153 } 154 155 @Override 156 public void onCreate(Bundle bundle) { 157 final Intent intent = getIntent(); 158 final Uri data = intent != null ? intent.getData() : null; 159 if (data != null) { 160 final int match = sUrlMatcher.match(data); 161 switch (match) { 162 case MATCH_LEGACY_SHORTCUT_INTENT: { 163 final long mailboxId = IntentUtilities.getMailboxIdFromIntent(intent); 164 final Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mailboxId); 165 if (mailbox == null) { 166 LogUtils.e(LOG_TAG, "unable to restore mailbox"); 167 break; 168 } 169 170 final Intent viewIntent = getViewIntent(mailbox.mAccountKey, mailboxId); 171 if (viewIntent != null) { 172 setIntent(viewIntent); 173 } 174 break; 175 } 176 } 177 } 178 179 super.onCreate(bundle); 180 final Preferences prefs = Preferences.getPreferences(this); 181 DEBUG = prefs.getEnableDebugLogging(); 182 enableStrictMode(prefs.getEnableStrictMode()); 183 TempDirectory.setTempDirectory(this); 184 185 // Enable logging in the EAS service, so it starts up as early as possible. 186 updateLoggingFlags(this); 187 188 // Make sure all required services are running when the app is started (can prevent 189 // issues after an adb sync/install) 190 setServicesEnabledAsync(this); 191 } 192 193 /** 194 * Load enabled debug flags from the preferences and update the EAS debug flag. 195 */ 196 public static void updateLoggingFlags(Context context) { 197 Preferences prefs = Preferences.getPreferences(context); 198 int debugLogging = prefs.getEnableDebugLogging() ? EmailServiceProxy.DEBUG_BIT : 0; 199 int verboseLogging = 200 prefs.getEnableExchangeLogging() ? EmailServiceProxy.DEBUG_VERBOSE_BIT : 0; 201 int fileLogging = 202 prefs.getEnableExchangeFileLogging() ? EmailServiceProxy.DEBUG_FILE_BIT : 0; 203 int enableStrictMode = 204 prefs.getEnableStrictMode() ? EmailServiceProxy.DEBUG_ENABLE_STRICT_MODE : 0; 205 int debugBits = debugLogging | verboseLogging | fileLogging | enableStrictMode; 206 EmailServiceUtils.setRemoteServicesLogging(context, debugBits); 207 } 208 209 /** 210 * Internal, utility method for logging. 211 * The calls to log() must be guarded with "if (Email.LOGD)" for performance reasons. 212 */ 213 public static void log(String message) { 214 LogUtils.d(Logging.LOG_TAG, message); 215 } 216 217 public static void enableStrictMode(boolean enabled) { 218 Utility.enableStrictMode(enabled); 219 } 220 221 private Intent getViewIntent(long accountId, long mailboxId) { 222 final ContentResolver contentResolver = getContentResolver(); 223 224 final Cursor accountCursor = contentResolver.query( 225 EmailProvider.uiUri("uiaccount", accountId), 226 UIProvider.ACCOUNTS_PROJECTION_NO_CAPABILITIES, 227 null, null, null); 228 229 if (accountCursor == null) { 230 LogUtils.e(LOG_TAG, "Null account cursor for mAccountId %d", accountId); 231 return null; 232 } 233 234 com.android.mail.providers.Account account = null; 235 try { 236 if (accountCursor.moveToFirst()) { 237 account = com.android.mail.providers.Account.builder().buildFrom(accountCursor); 238 } 239 } finally { 240 accountCursor.close(); 241 } 242 243 244 final Cursor folderCursor = contentResolver.query( 245 EmailProvider.uiUri("uifolder", mailboxId), 246 UIProvider.FOLDERS_PROJECTION, null, null, null); 247 248 if (folderCursor == null) { 249 LogUtils.e(LOG_TAG, "Null folder cursor for account %d, mailbox %d", 250 accountId, mailboxId); 251 return null; 252 } 253 254 Folder folder = null; 255 try { 256 if (folderCursor.moveToFirst()) { 257 folder = new Folder(folderCursor); 258 } else { 259 LogUtils.e(LOG_TAG, "Empty folder cursor for account %d, mailbox %d", 260 accountId, mailboxId); 261 return null; 262 } 263 } finally { 264 folderCursor.close(); 265 } 266 267 return Utils.createViewFolderIntent(this, folder.folderUri.fullUri, account); 268 } 269 } 270