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