16ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook/*******************************************************************************
26ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      Copyright (C) 2012 Google Inc.
36ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      Licensed to The Android Open Source Project.
46ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *
56ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      Licensed under the Apache License, Version 2.0 (the "License");
66ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      you may not use this file except in compliance with the License.
76ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      You may obtain a copy of the License at
86ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *
96ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *           http://www.apache.org/licenses/LICENSE-2.0
106ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *
116ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      Unless required by applicable law or agreed to in writing, software
126ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      distributed under the License is distributed on an "AS IS" BASIS,
136ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
146ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      See the License for the specific language governing permissions and
156ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *      limitations under the License.
166ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook *******************************************************************************/
176ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
186ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookpackage com.android.mail.ui;
196ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
206ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport com.android.mail.providers.Account;
216ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport com.android.mail.providers.Folder;
226ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport com.android.mail.providers.UIProvider;
23b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
246ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport com.android.mail.utils.LogUtils;
256ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport com.android.mail.ConversationListContext;
266ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
276ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.net.Uri;
286ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
296ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.content.BroadcastReceiver;
306ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.content.Context;
316ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.content.Intent;
326ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.content.IntentFilter;
336ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.content.IntentFilter.MalformedMimeTypeException;
346ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookimport android.text.TextUtils;
356ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
366ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
376ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook/**
38d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy * A simple {@code BroadcastReceiver} which suppresses new e-mail notifications for a given folder.
396ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook */
406ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrookpublic class SuppressNotificationReceiver extends BroadcastReceiver {
41b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    private static final String LOG_TAG = LogTag.getLogTag();
426ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
436ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    private Context mContext;
446ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    private AbstractActivityController mController;
456ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    private String mMimeType;
466ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
476ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    /**
48d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy     * Registers this receiver to suppress the new mail notifications for a given folder so
496ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     * that other {@code BroadcastReceiver}s don't receive them.
506ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     */
516ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    public boolean activate(Context context, AbstractActivityController controller) {
526ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final Account account = controller.getCurrentAccount();
536ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
546ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        mContext = context;
556ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        mController = controller;
566ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
576ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final IntentFilter filter = new IntentFilter(UIProvider.ACTION_UPDATE_NOTIFICATION);
586ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
596ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // Note: the real notification receiver must have a lower (i.e. negative) priority
606ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // than this receiver.
616ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        filter.setPriority(0);
626ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (account != null) {
636ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            mMimeType = account.mimeType;
646ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            try {
656ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                filter.addDataType(mMimeType);
666ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            } catch (MalformedMimeTypeException e) {
676ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                LogUtils.wtf(LOG_TAG, "Malformed mimetype: %s", mMimeType);
686ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            }
696ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        } else {
706ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // If the current account is null, still register the receiver.  This allows the
716ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // internal state of the receiver to match what the caller requested.
726ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            LogUtils.d(LOG_TAG, "Registering receiver with no mime type");
736ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
746ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        context.registerReceiver(this, filter);
756ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
766ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        return true;
776ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    }
786ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
796ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    /**
806ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     * Returns true if this suppressNotificationReceiver is activated
816ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     */
826ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    public boolean activated() {
836ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        return mContext != null;
846ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    }
856ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
866ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    /**
876ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     * Unregisters this receiver.
886ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     */
896ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    public void deactivate() {
906ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        try {
916ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            if (mContext != null) {
926ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                mContext.unregisterReceiver(this);
936ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                mContext = null;
946ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                mMimeType = null;
956ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            }
966ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        } catch (IllegalArgumentException e) {
976ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // May throw if already unregistered. Ignore exception.
986ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
996ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    }
1006ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1016ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    /**
1026ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     * Returns a boolean indicating whether notifications are suppressed for the specified account.
1036ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook     */
1046ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    public boolean notificationsDisabledForAccount(Account account) {
105c4b9ca097025e8f9541ffb03c66d25bd7835242fMindy Pereira        return mContext != null && TextUtils.equals(account.mimeType, mMimeType);
1066ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    }
1076ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1086ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    @Override
1096ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    public void onReceive(Context context, Intent intent) {
1106ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final String action = intent.getAction();
1116ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (!UIProvider.ACTION_UPDATE_NOTIFICATION.equals(action)) {
1126ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1136ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1146ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1156ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (!mController.isConversationListVisible()) {
1166ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // The conversation list is not visible, don't suppress notifications.
1176ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1186ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1196ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1206ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final ConversationListContext listContext = mController.getCurrentListContext();
1216ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (listContext == null) {
1226ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // A non-null list context was expected
12300a77fa36c722d750e13781c9aa8b8eb7320c71bPaul Westbrook            LogUtils.e(LOG_TAG, "unexpected null context");
1246ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1256ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1266ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
127ae4ea997d3d3f3c8c11fc5a3e7f9d49f82b4e2e7Vikram Aggarwal        if (ConversationListContext.isSearchResult(listContext)) {
1286ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            // The user is looking at a search result, don't suppress notifications.
1296ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1306ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1316ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1326ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final Account listContextAccount = listContext.account;
1336ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final Folder listContextFolder = listContext.folder;
1341672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal        // Guard against degenerate state in the controller
1351672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal        if (listContextAccount == null || listContextFolder == null) {
1361672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal            LogUtils.e(LOG_TAG, "SuppressNotificationReceiver.onReceive: account=%s, folder=%s",
1371672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal                    listContextAccount, listContextFolder);
1381672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal            return;
1391672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal        }
1406ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
1416ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final Uri intentAccountUri =
1426ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                (Uri)intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_ACCOUNT);
1436ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (!listContextAccount.uri.equals(intentAccountUri)) {
1446ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1456ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1466ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final Uri intentFolderUri =
1476ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                (Uri)intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_FOLDER);
1486ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook
149259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy        if (!listContextFolder.folderUri.equals(intentFolderUri)) {
1506ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1516ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1526ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        final int count = intent.getIntExtra(
1536ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                UIProvider.UpdateNotificationExtras.EXTRA_UPDATED_UNREAD_COUNT, 0);
1546ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // If the count is zero we want to let the intent through so that the
1556ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // regular receiver can remove the notification.
1566ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // This will allow a server change, that modifies the unread count to 0, to be handled
1576ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        // by the intended recpient to clear the notification.
1586ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        if (count == 0) {
1596ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook            return;
1606ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        }
1616ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        LogUtils.i(LOG_TAG, "Aborting broadcast of intent %s, folder uri is %s",
1626ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook                intent, intentFolderUri);
1636ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook        abortBroadcast();
1646ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook    }
1656ead20dd9643e6435d6c1111f99c520870812ea8Paul Westbrook}
166