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