150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/*
250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Copyright (C) 2011 The Android Open Source Project
350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby *
450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * you may not use this file except in compliance with the License.
650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * You may obtain a copy of the License at
750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby *
850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby *
1050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Unless required by applicable law or agreed to in writing, software
1150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
1250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * See the License for the specific language governing permissions and
1450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * limitations under the License.
1550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */
1650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
1750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypackage com.android.cellbroadcastreceiver;
1850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
1950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.app.AlertDialog;
2050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.app.KeyguardManager;
2150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Context;
2250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.DialogInterface;
2350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Intent;
2450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.graphics.drawable.Drawable;
2550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.os.Bundle;
2650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.os.Handler;
2750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.os.Message;
2850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.view.WindowManager;
2950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.widget.ImageView;
3050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
3150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/**
3250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Custom alert dialog with optional flashing warning icon.
3350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Alert audio and text-to-speech handled by {@link CellBroadcastAlertAudio}.
3450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */
3550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypublic class CellBroadcastAlertDialog extends AlertDialog {
3650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
3750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Whether to show the flashing warning icon. */
3850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private final boolean mShowWarningIcon;
3950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
4050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** The broadcast delivery time, for marking as read (or 0). */
4150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private final long mDeliveryTime;
4250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
4350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Length of time for the warning icon to be visible. */
4450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private static final int WARNING_ICON_ON_DURATION_MSEC = 800;
4550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
4650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Length of time for the warning icon to be off. */
4750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private static final int WARNING_ICON_OFF_DURATION_MSEC = 800;
4850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
4950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Warning icon state. false = visible, true = off */
5050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private boolean mIconAnimationState;
5150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
5250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Stop animating icon after {@link #onStop()} is called. */
5350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private boolean mStopAnimation;
5450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
5550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** The warning icon Drawable. */
5650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private Drawable mWarningIcon;
5750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
5850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** The View containing the warning icon. */
5950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private ImageView mWarningIconView;
6050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
6150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Keyguard lock to show emergency alerts while in the lock screen. */
6250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private KeyguardManager.KeyguardLock mKeyguardLock;
6350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
6450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /** Icon animation handler for flashing warning alerts. */
6550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    private final Handler mAnimationHandler = new Handler() {
6650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        @Override
6750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        public void handleMessage(Message msg) {
6850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            if (mIconAnimationState) {
6950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                mWarningIconView.setAlpha(255);
7050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                if (!mStopAnimation) {
7150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    mAnimationHandler.sendEmptyMessageDelayed(0, WARNING_ICON_ON_DURATION_MSEC);
7250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                }
7350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            } else {
7450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                mWarningIconView.setAlpha(0);
7550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                if (!mStopAnimation) {
7650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    mAnimationHandler.sendEmptyMessageDelayed(0, WARNING_ICON_OFF_DURATION_MSEC);
7750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                }
7850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            }
7950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mIconAnimationState = !mIconAnimationState;
8050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mWarningIconView.invalidateDrawable(mWarningIcon);
8150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
8250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    };
8350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
8450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /**
8550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * Create a new alert dialog for the broadcast notification.
8650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * @param context the local Context
8750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * @param titleId the resource ID of the dialog title
8850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * @param body the message body contents
8950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * @param showWarningIcon true if the flashing warning icon should be shown
9050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * @param deliveryTime the delivery time of the broadcast, for marking as read
9150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     */
9250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    public CellBroadcastAlertDialog(Context context, int titleId, CharSequence body,
9350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            boolean showWarningIcon, long deliveryTime) {
9450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        super(context);
9550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        mShowWarningIcon = showWarningIcon;
9650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        mDeliveryTime = deliveryTime;
9750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
9850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        setTitle(titleId);
9950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        setMessage(body);
10050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        setCancelable(true);
10150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        setOnCancelListener(new AlertDialog.OnCancelListener() {
10250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            public void onCancel(DialogInterface dialog) {
10350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                dialog.dismiss();
10450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            }
10550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        });
10650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        setButton(DialogInterface.BUTTON_NEUTRAL, context.getText(R.string.button_dismiss),
10750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                new DialogInterface.OnClickListener() {
10850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    public void onClick(DialogInterface dialog, int whichButton) {
10950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                        dialog.dismiss();
11050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    }
11150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                });
11250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
11350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        // Set warning icon for emergency alert
11450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (mShowWarningIcon) {
11550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mWarningIcon = getContext().getResources().getDrawable(R.drawable.ic_warning_large);
11650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            setIcon(mWarningIcon);
11750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
11850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    }
11950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
12050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    @Override
12150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    protected void onCreate(Bundle savedInstanceState) {
12250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (mShowWarningIcon) {
12350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            // Turn screen on and show above the keyguard for emergency alert
12450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
12550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
12650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
12750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
12850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
12950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
13050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        super.onCreate(savedInstanceState);
13150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (mShowWarningIcon) {
13250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            KeyguardManager km = (KeyguardManager)
13350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby                    getContext().getSystemService(Context.KEYGUARD_SERVICE);
13450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mKeyguardLock = km.newKeyguardLock("CellBroadcastReceiver");
13550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mWarningIconView = (ImageView) findViewById(com.android.internal.R.id.icon);
13650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
13750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    }
13850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
13950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /**
14050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * Start animating warning icon.
14150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     */
14250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    @Override
14350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    protected void onStart() {
14450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (mShowWarningIcon) {
14550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            // Disable keyguard
14650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mKeyguardLock.disableKeyguard();
14750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            // start icon animation
14850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mAnimationHandler.sendEmptyMessageDelayed(0, WARNING_ICON_ON_DURATION_MSEC);
14950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
15050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    }
15150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
15250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /**
15350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * Stop animating warning icon and stop the {@link CellBroadcastAlertAudio}
15450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * service if necessary.
15550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     */
15650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    @Override
15750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    protected void onStop() {
15850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        // Stop playing alert sound/vibration/speech (if started)
15950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        Context context = getContext();
16050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        context.stopService(new Intent(context, CellBroadcastAlertAudio.class));
16150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        // Start database service to mark broadcast as read
16250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        Intent intent = new Intent(context, CellBroadcastDatabaseService.class);
16350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        intent.setAction(CellBroadcastDatabaseService.ACTION_MARK_BROADCAST_READ);
16450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        intent.putExtra(CellBroadcastDatabaseService.DATABASE_DELIVERY_TIME_EXTRA, mDeliveryTime);
16550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        context.startService(intent);
16650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (mShowWarningIcon) {
16750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            // Reenable keyguard
16850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mKeyguardLock.reenableKeyguard();
16950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            // stop animating icon
17050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            mStopAnimation = true;
17150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
17250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    }
17350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby
17450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    /**
17550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     * Ignore the back button for emergency alerts (user must dismiss with button).
17650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby     */
17750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    @Override
17850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    public void onBackPressed() {
17950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (!mShowWarningIcon) {
18050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            super.onBackPressed();
18150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        }
18250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby    }
18350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby}
184