EmailNotificationController.java revision d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577e
1899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki/*
2899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Copyright (C) 2010 The Android Open Source Project
3899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki *
4899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
5899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * you may not use this file except in compliance with the License.
6899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * You may obtain a copy of the License at
7899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki *
8899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
9899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki *
10899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Unless required by applicable law or agreed to in writing, software
11899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
12899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * See the License for the specific language governing permissions and
14899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * limitations under the License.
15899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */
16899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
17899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukipackage com.android.email;
18899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
19899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.activity.ContactStatusLoader;
20899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.activity.Welcome;
21d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport com.android.email.activity.setup.AccountSettingsXL;
22899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.mail.Address;
23899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent;
24899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent.Account;
25d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport com.android.email.provider.EmailContent.Attachment;
26899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport com.android.email.provider.EmailContent.Message;
27899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
28899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.Notification;
29899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.NotificationManager;
30899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.app.PendingIntent;
31899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.content.Context;
32d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blankimport android.content.Intent;
33899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.graphics.Bitmap;
34899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.graphics.BitmapFactory;
35899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.media.AudioManager;
36899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.net.Uri;
37899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukiimport android.text.TextUtils;
38899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
39899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki/**
40899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * Class that manages notifications.
41899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki *
42899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki * TODO Gather all notification related code here
43899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki */
44899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onukipublic class NotificationController {
45899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    public static final int NOTIFICATION_ID_SECURITY_NEEDED = 1;
46899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    public static final int NOTIFICATION_ID_EXCHANGE_CALENDAR_ADDED = 2;
47d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    public static final int NOTIFICATION_ID_ATTACHMENT_WARNING = 3;
48d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
49d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    private static final int NOTIFICATION_ID_BASE_NEW_MESSAGES = 0x10000000;
50d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    private static final int NOTIFICATION_ID_BASE_LOGIN_WARNING = 0x20000000;
51899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
52899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private static NotificationController sInstance;
53899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private final Context mContext;
54899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private final NotificationManager mNotificationManager;
55899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private final AudioManager mAudioManager;
56899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
57899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /** Constructor */
58899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private NotificationController(Context context) {
59899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        mContext = context.getApplicationContext();
60899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        mNotificationManager = (NotificationManager) context.getSystemService(
61899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                Context.NOTIFICATION_SERVICE);
62899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
63899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
64899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
65899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /** Singleton access */
66899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    public static synchronized NotificationController getInstance(Context context) {
67899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (sInstance == null) {
68899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            sInstance = new NotificationController(context);
69899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
70899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        return sInstance;
71899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
72899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
73899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /**
74899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * @return the "new message" notification ID for an account. It just assumes
75899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     *         accountID won't be too huge. Any other smarter/cleaner way?
76899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     */
77899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private int getNewMessageNotificationId(long accountId) {
78d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        return (int) (NOTIFICATION_ID_BASE_NEW_MESSAGES + accountId);
79899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
80899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
81899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /**
82899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * Dismiss new message notification
83899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     *
84899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * @param accountId ID of the target account, or -1 for all accounts.
85899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     */
86899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    public void cancelNewMessageNotification(long accountId) {
87899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (accountId == -1) {
88899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            new Utility.ForEachAccount(mContext) {
89899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                @Override
90899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                protected void performAction(long accountId) {
91899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    cancelNewMessageNotification(accountId);
92899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                }
93899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            }.execute();
94899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        } else {
95899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            mNotificationManager.cancel(getNewMessageNotificationId(accountId));
96899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
97899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
98899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
99899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /**
100899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * Show (or update) the "new message" notification.
101899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     */
102899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    public void showNewMessageNotification(final long accountId, final int unseenMessageCount,
103899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            final int justFetchedCount) {
104899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        Utility.runAsync(new Runnable() {
105899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            @Override
106899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            public void run() {
107899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                Notification n = createNewMessageNotification(accountId, unseenMessageCount,
108899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                        justFetchedCount);
109899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                if (n == null) {
110899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    return;
111899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                }
112899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                mNotificationManager.notify(getNewMessageNotificationId(accountId), n);
113899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            }
114899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        });
115899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
116899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
117899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /**
118899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * @return The sender's photo, if available, or null.
119899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     *
120899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * Don't call it on the UI thread.
121899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     */
122899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private Bitmap getSenderPhoto(Message message) {
123899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        Address sender = Address.unpackFirst(message.mFrom);
124899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (sender == null) {
125899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return null;
126899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
127899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        String email = sender.getAddress();
128899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (TextUtils.isEmpty(email)) {
129899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return null;
130899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
131899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        return ContactStatusLoader.load(mContext, email).mPhoto;
132899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
133899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
134899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private Bitmap[] getNotificationBitmaps(Bitmap senderPhoto) {
135899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // TODO Should we cache these objects?  (bitmaps and arrays)
136899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // They don't have to be on this process's memory once we post a notification request to
137899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // the system, and decodeResource() seems to be reasonably fast.  We don't want them to
138899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // take up memory when not necessary.
139899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        Bitmap appIcon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.icon);
140899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (senderPhoto == null) {
141899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return new Bitmap[] {appIcon};
142899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        } else {
143899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return new Bitmap[] {senderPhoto, appIcon};
144899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
145899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
146899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
147899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    /**
148899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * Create a notification
149899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     *
150899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * Don't call it on the UI thread.
151899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     *
152899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     * TODO Test it when the UI is settled.
153899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki     */
154899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private Notification createNewMessageNotification(long accountId, int unseenMessageCount,
155899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            int justFetchedCount) {
156899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final Account account = Account.restoreAccountWithId(mContext, accountId);
157899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (account == null) {
158899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return null;
159899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
160899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // Get the latest message
161899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final Message message = Message.getLatestMessage(mContext, accountId);
162899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (message == null) {
163899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            return null; // no message found???
164899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
165899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
166899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String senderName = Address.toFriendly(Address.unpack(message.mFrom));
167899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String subject = message.mSubject;
168899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final Bitmap senderPhoto = getSenderPhoto(message);
169899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
170899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // Intent to open inbox
171899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0,
172899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                Welcome.createOpenAccountInboxIntent(mContext, accountId),
173899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                PendingIntent.FLAG_UPDATE_CURRENT);
174899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
175899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String notificationTitle;
176899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (justFetchedCount == 1) {
177899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            notificationTitle = senderName;
178899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        } else {
179899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            notificationTitle = mContext.getResources().getQuantityString(
180899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    R.plurals.notification_sender_name_multi_messages, justFetchedCount - 1,
181899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    senderName, justFetchedCount - 1);
182899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
183899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String content = subject;
184899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String numNewMessages;
185899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final int numAccounts = EmailContent.count(mContext, Account.CONTENT_URI);
186899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (numAccounts == 1) {
187899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            numNewMessages = mContext.getResources().getQuantityString(
188899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    R.plurals.notification_num_new_messages_single_account, unseenMessageCount,
189899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    unseenMessageCount, account.mDisplayName);
190899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        } else {
191899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            numNewMessages = mContext.getResources().getQuantityString(
192899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    R.plurals.notification_num_new_messages_multi_account, unseenMessageCount,
193899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                    unseenMessageCount, account.mDisplayName);
194899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
195899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
196899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        Notification notification = new Notification(R.drawable.stat_notify_email_generic,
197899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki                mContext.getString(R.string.notification_new_title), System.currentTimeMillis());
198899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.setLatestEventInfo(mContext, notificationTitle, subject, contentIntent);
199899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
200899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.tickerTitle = notificationTitle;
201899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // STOPSHIPO numNewMessages should be the 3rd line on expanded notification.  But it's not
202899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // clear how to do that yet.
203899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // For now we just append it to subject.
204899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.tickerSubtitle = subject + "  " + numNewMessages;
205899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.tickerIcons = getNotificationBitmaps(senderPhoto);
206899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
207899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        setupNotificationSoundAndVibrationFromAccount(notification, account);
208899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        return notification;
209899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
210899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
211899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private boolean isRingerModeSilent() {
212899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
213899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
214899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
215899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    private void setupNotificationSoundAndVibrationFromAccount(Notification notification,
216899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            Account account) {
217899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final int flags = account.mFlags;
218899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final String ringtoneUri = account.mRingtoneUri;
219899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final boolean vibrate = (flags & Account.FLAGS_VIBRATE_ALWAYS) != 0;
220899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        final boolean vibrateWhenSilent = (flags & Account.FLAGS_VIBRATE_WHEN_SILENT) != 0;
221899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
222899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.sound = (ringtoneUri == null) ? null : Uri.parse(ringtoneUri);
223899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
224899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        if (vibrate || (vibrateWhenSilent && isRingerModeSilent())) {
225899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki            notification.defaults |= Notification.DEFAULT_VIBRATE;
226899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        }
227899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki
228899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        // This code is identical to that used by Gmail and GTalk for notifications
229899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
230899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki        notification.defaults |= Notification.DEFAULT_LIGHTS;
231899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki    }
232d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
233d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    /**
234d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     * Generic warning notification
235d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     */
236d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    public void showWarningNotification(int id, String tickerText, String notificationText,
237d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank            Intent intent) {
238d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        PendingIntent pendingIntent =
239d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank            PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
240d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        Notification n = new Notification(android.R.drawable.stat_notify_error, tickerText,
241d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                System.currentTimeMillis());
242d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        n.setLatestEventInfo(mContext, tickerText, notificationText, pendingIntent);
243d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        n.flags = Notification.FLAG_AUTO_CANCEL;
244d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        mNotificationManager.notify(id, n);
245d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    }
246d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
247d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    /**
248d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     * Alert the user that an attachment couldn't be forwarded.  This is a very unusual case, and
249d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     * perhaps we shouldn't even send a notification. For now, it's helpful for debugging.
250d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     */
251d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    public void showDownloadForwardFailedNotification(Attachment att) {
252d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        showWarningNotification(NOTIFICATION_ID_ATTACHMENT_WARNING,
253d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                mContext.getString(R.string.forward_download_failed_ticker),
254d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                mContext.getString(R.string.forward_download_failed_notification,
255d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                        att.mFileName),
256d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                Welcome.createOpenCombinedOutboxIntent(mContext));
257d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    }
258d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
259d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    /**
260d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     * Alert the user that login failed for the specified account
261d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank     */
262d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    private int getLoginFailedNotificationId(long accountId) {
263d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        return NOTIFICATION_ID_BASE_LOGIN_WARNING + (int)accountId;
264d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    }
265d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
266d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    // NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
267d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    public void showLoginFailedNotification(long accountId) {
268d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        final Account account = Account.restoreAccountWithId(mContext, accountId);
269d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        if (account == null) return;
270d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        showWarningNotification(getLoginFailedNotificationId(accountId),
271d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                mContext.getString(R.string.login_failed_ticker, account.mDisplayName),
272d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                mContext.getString(R.string.login_failed_notification),
273d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank                AccountSettingsXL.createAccountSettingsIntent(mContext, accountId));
274d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    }
275d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank
276d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    public void cancelLoginFailedNotification(long accountId) {
277d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank        mNotificationManager.cancel(getLoginFailedNotificationId(accountId));
278d3e4f3ca7e43fb7ebaa140f93a44a1fb96a0577eMarc Blank    }
279899c5b866192a4c4a12413446d10e5d98dbf94faMakoto Onuki}
280