Email.java revision 4f813fb12937de74d3ccec730b8de0c9de7a87e0
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 17package com.android.email; 18 19import android.app.Application; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.Intent; 23import android.content.pm.PackageManager; 24import android.database.Cursor; 25import android.util.Log; 26 27import com.android.email.activity.MessageCompose; 28import com.android.email.activity.ShortcutPicker; 29import com.android.email.service.AttachmentDownloadService; 30import com.android.email.service.MailService; 31import com.android.emailcommon.Logging; 32import com.android.emailcommon.TempDirectory; 33import com.android.emailcommon.provider.Account; 34import com.android.emailcommon.service.EmailServiceProxy; 35import com.android.emailcommon.utility.EmailAsyncTask; 36import com.android.emailcommon.utility.Utility; 37 38public class Email extends Application { 39 /** 40 * If this is enabled there will be additional logging information sent to 41 * Log.d, including protocol dumps. 42 * 43 * This should only be used for logs that are useful for debbuging user problems, 44 * not for internal/development logs. 45 * 46 * This can be enabled by typing "debug" in the AccountFolderList activity. 47 * Changing the value to 'true' here will likely have no effect at all! 48 * 49 * TODO: rename this to sUserDebug, and rename LOGD below to DEBUG. 50 */ 51 public static boolean DEBUG; 52 53 // Exchange debugging flags (passed to Exchange, when available, via EmailServiceProxy) 54 public static boolean DEBUG_EXCHANGE; 55 public static boolean DEBUG_EXCHANGE_VERBOSE; 56 public static boolean DEBUG_EXCHANGE_FILE; 57 58 /** 59 * If true, inhibit hardware graphics acceleration in UI (for a/b testing) 60 */ 61 public static boolean sDebugInhibitGraphicsAcceleration = false; 62 63 /** 64 * Specifies how many messages will be shown in a folder by default. This number is set 65 * on each new folder and can be incremented with "Load more messages..." by the 66 * VISIBLE_LIMIT_INCREMENT 67 */ 68 public static final int VISIBLE_LIMIT_DEFAULT = 25; 69 70 /** 71 * Number of additional messages to load when a user selects "Load more messages..." 72 */ 73 public static final int VISIBLE_LIMIT_INCREMENT = 25; 74 75 /** 76 * This is used to force stacked UI to return to the "welcome" screen any time we change 77 * the accounts list (e.g. deleting accounts in the Account Manager preferences.) 78 */ 79 private static boolean sAccountsChangedNotification = false; 80 81 private static String sMessageDecodeErrorString; 82 83 private static Thread sUiThread; 84 85 /** 86 * Asynchronous version of {@link #setServicesEnabledSync(Context)}. Use when calling from 87 * UI thread (or lifecycle entry points.) 88 * 89 * @param context 90 */ 91 public static void setServicesEnabledAsync(final Context context) { 92 EmailAsyncTask.runAsyncParallel(new Runnable() { 93 @Override 94 public void run() { 95 setServicesEnabledSync(context); 96 } 97 }); 98 } 99 100 /** 101 * Called throughout the application when the number of accounts has changed. This method 102 * enables or disables the Compose activity, the boot receiver and the service based on 103 * whether any accounts are configured. 104 * 105 * Blocking call - do not call from UI/lifecycle threads. 106 * 107 * @param context 108 * @return true if there are any accounts configured. 109 */ 110 public static boolean setServicesEnabledSync(Context context) { 111 Cursor c = null; 112 try { 113 c = context.getContentResolver().query( 114 Account.CONTENT_URI, 115 Account.ID_PROJECTION, 116 null, null, null); 117 boolean enable = c.getCount() > 0; 118 setServicesEnabled(context, enable); 119 return enable; 120 } finally { 121 if (c != null) { 122 c.close(); 123 } 124 } 125 } 126 127 private static void setServicesEnabled(Context context, boolean enabled) { 128 PackageManager pm = context.getPackageManager(); 129 pm.setComponentEnabledSetting( 130 new ComponentName(context, MessageCompose.class), 131 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 132 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 133 PackageManager.DONT_KILL_APP); 134 pm.setComponentEnabledSetting( 135 new ComponentName(context, ShortcutPicker.class), 136 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 137 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 138 PackageManager.DONT_KILL_APP); 139 pm.setComponentEnabledSetting( 140 new ComponentName(context, MailService.class), 141 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 142 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 143 PackageManager.DONT_KILL_APP); 144 pm.setComponentEnabledSetting( 145 new ComponentName(context, AttachmentDownloadService.class), 146 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 147 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 148 PackageManager.DONT_KILL_APP); 149 150 // Start/stop the various services depending on whether there are any accounts 151 startOrStopService(enabled, context, new Intent(context, AttachmentDownloadService.class)); 152 NotificationController.getInstance(context).watchForMessages(enabled); 153 } 154 155 /** 156 * Starts or stops the service as necessary. 157 * @param enabled If {@code true}, the service will be started. Otherwise, it will be stopped. 158 * @param context The context to manage the service with. 159 * @param intent The intent of the service to be managed. 160 */ 161 private static void startOrStopService(boolean enabled, Context context, Intent intent) { 162 if (enabled) { 163 context.startService(intent); 164 } else { 165 context.stopService(intent); 166 } 167 } 168 169 @Override 170 public void onCreate() { 171 super.onCreate(); 172 sUiThread = Thread.currentThread(); 173 Preferences prefs = Preferences.getPreferences(this); 174 DEBUG = prefs.getEnableDebugLogging(); 175 sDebugInhibitGraphicsAcceleration = prefs.getInhibitGraphicsAcceleration(); 176 enableStrictMode(prefs.getEnableStrictMode()); 177 TempDirectory.setTempDirectory(this); 178 179 // Tie MailRefreshManager to the Controller. 180 RefreshManager.getInstance(this); 181 // Reset all accounts to default visible window 182 Controller.getInstance(this).resetVisibleLimits(); 183 184 // Enable logging in the EAS service, so it starts up as early as possible. 185 updateLoggingFlags(this); 186 187 // Get a helper string used deep inside message decoders (which don't have context) 188 sMessageDecodeErrorString = getString(R.string.message_decode_error); 189 190 // Make sure all required services are running when the app is started (can prevent 191 // issues after an adb sync/install) 192 setServicesEnabledAsync(this); 193 } 194 195 /** 196 * Load enabled debug flags from the preferences and update the EAS debug flag. 197 */ 198 public static void updateLoggingFlags(Context context) { 199 Preferences prefs = Preferences.getPreferences(context); 200 int debugLogging = prefs.getEnableDebugLogging() ? EmailServiceProxy.DEBUG_BIT : 0; 201 int verboseLogging = 202 prefs.getEnableExchangeLogging() ? EmailServiceProxy.DEBUG_VERBOSE_BIT : 0; 203 int fileLogging = 204 prefs.getEnableExchangeFileLogging() ? EmailServiceProxy.DEBUG_FILE_BIT : 0; 205 int enableStrictMode = 206 prefs.getEnableStrictMode() ? EmailServiceProxy.DEBUG_ENABLE_STRICT_MODE : 0; 207 int debugBits = debugLogging | verboseLogging | fileLogging | enableStrictMode; 208 Controller.getInstance(context).serviceLogging(debugBits); 209 } 210 211 /** 212 * Internal, utility method for logging. 213 * The calls to log() must be guarded with "if (Email.LOGD)" for performance reasons. 214 */ 215 public static void log(String message) { 216 Log.d(Logging.LOG_TAG, message); 217 } 218 219 /** 220 * Called by the accounts reconciler to notify that accounts have changed, or by "Welcome" 221 * to clear the flag. 222 * @param setFlag true to set the notification flag, false to clear it 223 */ 224 public static synchronized void setNotifyUiAccountsChanged(boolean setFlag) { 225 sAccountsChangedNotification = setFlag; 226 } 227 228 /** 229 * Called from activity onResume() functions to check for an accounts-changed condition, at 230 * which point they should finish() and jump to the Welcome activity. 231 */ 232 public static synchronized boolean getNotifyUiAccountsChanged() { 233 return sAccountsChangedNotification; 234 } 235 236 public static void warnIfUiThread() { 237 if (Thread.currentThread().equals(sUiThread)) { 238 Log.w(Logging.LOG_TAG, "Method called on the UI thread", new Exception("STACK TRACE")); 239 } 240 } 241 242 /** 243 * Retrieve a simple string that can be used when message decoders encounter bad data. 244 * This is provided here because the protocol decoders typically don't have mContext. 245 */ 246 public static String getMessageDecodeErrorString() { 247 return sMessageDecodeErrorString != null ? sMessageDecodeErrorString : ""; 248 } 249 250 public static void enableStrictMode(boolean enabled) { 251 Utility.enableStrictMode(enabled); 252 } 253} 254