1 /******************************************************************************* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 *******************************************************************************/ 17 18 package com.android.mail.ui; 19 20 import com.android.mail.providers.Account; 21 import com.android.mail.providers.Folder; 22 import com.android.mail.providers.UIProvider; 23 import com.android.mail.utils.LogTag; 24 import com.android.mail.utils.LogUtils; 25 import com.android.mail.ConversationListContext; 26 27 import android.net.Uri; 28 29 import android.content.BroadcastReceiver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.content.IntentFilter.MalformedMimeTypeException; 34 import android.text.TextUtils; 35 36 37 /** 38 * A simple {@code BroadcastReceiver} which suppresses new e-mail notifications for a given folder. 39 */ 40 public class SuppressNotificationReceiver extends BroadcastReceiver { 41 private static final String LOG_TAG = LogTag.getLogTag(); 42 43 private Context mContext; 44 private AbstractActivityController mController; 45 private String mMimeType; 46 47 /** 48 * Registers this receiver to suppress the new mail notifications for a given folder so 49 * that other {@code BroadcastReceiver}s don't receive them. 50 */ 51 public boolean activate(Context context, AbstractActivityController controller) { 52 final Account account = controller.getCurrentAccount(); 53 54 mContext = context; 55 mController = controller; 56 57 final IntentFilter filter = new IntentFilter(UIProvider.ACTION_UPDATE_NOTIFICATION); 58 59 // Note: the real notification receiver must have a lower (i.e. negative) priority 60 // than this receiver. 61 filter.setPriority(0); 62 if (account != null) { 63 mMimeType = account.mimeType; 64 try { 65 filter.addDataType(mMimeType); 66 } catch (MalformedMimeTypeException e) { 67 LogUtils.wtf(LOG_TAG, "Malformed mimetype: %s", mMimeType); 68 } 69 } else { 70 // If the current account is null, still register the receiver. This allows the 71 // internal state of the receiver to match what the caller requested. 72 LogUtils.d(LOG_TAG, "Registering receiver with no mime type"); 73 } 74 context.registerReceiver(this, filter); 75 76 return true; 77 } 78 79 /** 80 * Returns true if this suppressNotificationReceiver is activated 81 */ 82 public boolean activated() { 83 return mContext != null; 84 } 85 86 /** 87 * Unregisters this receiver. 88 */ 89 public void deactivate() { 90 try { 91 if (mContext != null) { 92 mContext.unregisterReceiver(this); 93 mContext = null; 94 mMimeType = null; 95 } 96 } catch (IllegalArgumentException e) { 97 // May throw if already unregistered. Ignore exception. 98 } 99 } 100 101 /** 102 * Returns a boolean indicating whether notifications are suppressed for the specified account. 103 */ 104 public boolean notificationsDisabledForAccount(Account account) { 105 return mContext != null && TextUtils.equals(account.mimeType, mMimeType); 106 } 107 108 @Override 109 public void onReceive(Context context, Intent intent) { 110 final String action = intent.getAction(); 111 if (!UIProvider.ACTION_UPDATE_NOTIFICATION.equals(action)) { 112 return; 113 } 114 115 if (!mController.isConversationListVisible()) { 116 // The conversation list is not visible, don't suppress notifications. 117 return; 118 } 119 120 final ConversationListContext listContext = mController.getCurrentListContext(); 121 if (listContext == null) { 122 // A non-null list context was expected 123 LogUtils.e(LOG_TAG, "unexpected null context"); 124 return; 125 } 126 127 if (ConversationListContext.isSearchResult(listContext)) { 128 // The user is looking at a search result, don't suppress notifications. 129 return; 130 } 131 132 final Account listContextAccount = listContext.account; 133 final Folder listContextFolder = listContext.folder; 134 // Guard against degenerate state in the controller 135 if (listContextAccount == null || listContextFolder == null) { 136 LogUtils.e(LOG_TAG, "SuppressNotificationReceiver.onReceive: account=%s, folder=%s", 137 listContextAccount, listContextFolder); 138 return; 139 } 140 141 final Uri intentAccountUri = 142 (Uri)intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_ACCOUNT); 143 if (!listContextAccount.uri.equals(intentAccountUri)) { 144 return; 145 } 146 final Uri intentFolderUri = 147 (Uri)intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_FOLDER); 148 149 if (!listContextFolder.folderUri.equals(intentFolderUri)) { 150 return; 151 } 152 final int count = intent.getIntExtra( 153 UIProvider.UpdateNotificationExtras.EXTRA_UPDATED_UNREAD_COUNT, 0); 154 // If the count is zero we want to let the intent through so that the 155 // regular receiver can remove the notification. 156 // This will allow a server change, that modifies the unread count to 0, to be handled 157 // by the intended recpient to clear the notification. 158 if (count == 0) { 159 return; 160 } 161 LogUtils.i(LOG_TAG, "Aborting broadcast of intent %s, folder uri is %s", 162 intent, intentFolderUri); 163 abortBroadcast(); 164 } 165 } 166