<activity android:name="SetAlarm" android:label="@string/set_alarm"
android:configChanges="orientation|keyboardHidden|keyboard|navigation" />
- <activity android:name="AlarmAlert" android:label="@string/alert_title"
+ <activity android:name="AlarmAlert"
android:excludeFromRecents="true"
- android:theme="@android:style/Theme.Dialog"
+ android:theme="@style/alarm_alert"
android:launchMode="singleTask"
android:taskAffinity=":AlarmAlert"
- android:screenOrientation="nosensor"
- android:configChanges="orientation|keyboardHidden|keyboard|navigation" />
+ android:screenOrientation="portrait"
+ android:configChanges="orientation|keyboardHidden|keyboard|navigation"/>
+
+ <!-- This activity is basically the same as AlarmAlert but with a more
+ generic theme. It also shows as full screen (with status bar) but
+ with the wallpaper background. -->
+ <activity android:name="AlarmAlertFullScreen"
+ android:excludeFromRecents="true"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:launchMode="singleTask"
+ android:taskAffinity=":AlarmAlert"
+ android:screenOrientation="portrait"
+ android:configChanges="orientation|keyboardHidden|keyboard|navigation"/>
<activity android:name="ClockPicker" />
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/root"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:paddingTop="2dp">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/clockView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"/>
-
- <TextView android:id="@+id/silencedText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="4dp"
- android:paddingTop="2dp"
- android:paddingBottom="2dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone"
- android:gravity="center"
- android:textColor="@color/red"
- android:text="@string/alarm_alert_alert_silenced"/>
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:orientation="vertical">
-
- <Button
- android:id="@+id/snooze"
- android:layout_width="108dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/alarm_alert_snooze_text" />
-
- <!-- blank stretchable view -->
- <View
- android:layout_width="2dip"
- android:layout_gravity="fill_vertical"
- android:layout_weight="1"
- android:layout_height="2dip"/>
-
- <Button
- android:id="@+id/dismiss"
- android:layout_width="108dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/alarm_alert_dismiss_text" />
-
- </LinearLayout>
-
-</LinearLayout>
<FrameLayout
android:id="@+id/clock_layout"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip"/>
+ android:layout_width="208dip"
+ android:layout_height="fill_parent"/>
<ListView
android:id="@+id/alarms_list"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/root"
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical">
+ android:layout_height="fill_parent">
<LinearLayout
- android:id="@+id/clockView"
- android:layout_width="208dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"/>
+ android:layout_gravity="center"
+ android:gravity="center_horizontal"
+ android:background="@drawable/dialog"
+ android:orientation="vertical">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingTop="4dp">
+ <TextView android:id="@+id/alertTitle"
+ style="?android:attr/textAppearanceLarge"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:gravity="center"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:scaleType="fitXY"
+ android:gravity="fill_horizontal"
+ android:src="@*android:drawable/dialog_divider_horizontal_light"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="10dip"/>
+
+ <LinearLayout
+ android:id="@+id/clockView"
+ android:layout_width="210dip"
+ android:layout_height="210dip"
+ android:gravity="center"/>
- <Button
- android:id="@+id/snooze"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingBottom="24dp"
- android:layout_weight="3"
- android:text="@string/alarm_alert_snooze_text" />
+ style="@android:style/ButtonBar">
+
+ <Button
+ android:id="@+id/snooze"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:text="@string/alarm_alert_snooze_text" />
- <!-- blank stretchable view -->
- <View
- android:layout_width="2dip"
- android:layout_height="2dip"
- android:layout_gravity="fill_horizontal"
- android:layout_weight="1"/>
-
- <Button
- android:id="@+id/dismiss"
+ <!-- blank stretchable view -->
+ <View
+ android:layout_width="2dip"
+ android:layout_height="2dip"
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/dismiss"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:text="@string/alarm_alert_dismiss_text" />
+
+ </LinearLayout>
+
+ <TextView android:id="@+id/silencedText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingBottom="24dp"
- android:layout_weight="3"
- android:text="@string/alarm_alert_dismiss_text" />
+ android:paddingTop="2dp"
+ android:paddingBottom="2dp"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:visibility="gone"
+ android:gravity="center"
+ android:textColor="@color/red"/>
</LinearLayout>
-
- <TextView android:id="@+id/silencedText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="2dp"
- android:paddingBottom="2dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone"
- android:gravity="center"
- android:textColor="@color/red"/>
-
</LinearLayout>
<LinearLayout
android:id="@+id/clock_layout"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"/>
+ android:layout_height="192dip"/>
<ListView
android:id="@+id/alarms_list"
<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clock"
- style="@style/analogClock"
+ style="@style/clock"
android:dial="@drawable/clock_dial"
android:hand_hour="@drawable/clock_hour"
android:hand_minute="@drawable/clock_minute"/>
<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clock"
- style="@style/analogClock"
+ style="@style/clock"
android:dial="@drawable/clockdroid2_dial"
android:hand_hour="@drawable/clockdroid2_hour"
android:hand_minute="@drawable/clockdroid2_minute"/>
<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clock"
- style="@style/analogClock"
+ style="@style/clock"
android:dial="@drawable/clockdroids_dial"
android:hand_hour="@drawable/clockdroids_hour"
android:hand_minute="@drawable/clockdroids_minute"/>
<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clock"
- style="@style/analogClock"
+ style="@style/clock"
android:dial="@drawable/clockgoog_dial"
android:hand_hour="@drawable/clockgoog_hour"
android:hand_minute="@drawable/clockgoog_minute"/>
limitations under the License.
-->
-<com.android.alarmclock.DigitalClock android:id="@+id/digitalClock"
+<com.android.alarmclock.DigitalClock android:id="@+id/clock"
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ style="@style/clock"
android:gravity="center">
<!-- Includes vertical padding so animated background doesn't
<TextView android:id="@+id/timeDisplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:gravity="center"
android:textSize="64sp"
- android:paddingTop="48dip"
- android:paddingBottom="48dip"
android:textColor="@color/white"/>
<LinearLayout android:id="@+id/am_pm"
-->
<resources>
- <style name="analogClock">
+ <style name="clock">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:layout_gravity">center_horizontal</item>
</style>
+
+ <!-- This theme is similar to the Theme.Dialog.Alert but does not rely on a
+ non-public resource. -->
+ <style name="alarm_alert" parent="android:Theme.Dialog">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
</resources>
// Maintain a lock during the playback of the alarm. This lock may have
// already been acquired in AlarmReceiver. If the process was killed,
// the global wake lock is gone. Acquire again just to be sure.
- AlarmAlertWakeLock.acquire(this);
+ AlarmAlertWakeLock.acquireCpuWakeLock(this);
/* FIXME Intentionally verbose: always log this until we've
fully debugged the app failing to start up */
Log.v("AlarmAlert.onCreate()");
- // Popup alert over black screen
- WindowManager.LayoutParams lp = getWindow().getAttributes();
- lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
- lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- // XXX DO NOT COPY THIS!!! THIS IS BOGUS! Making an activity have
- // a system alert type is completely broken, because the activity
- // manager will still hide/show it as if it is part of the normal
- // activity stack. If this is really what you want and you want it
- // to work correctly, you should create and show your own custom window.
- lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
- lp.token = null;
- Window win = getWindow();
- win.setAttributes(lp);
- // TODO Make the activity full screen for FLAG_SHOW_WHEN_LOCKED to bypass
- // the key guard.
- win.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND |
- WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
-
Intent i = getIntent();
mAlarmId = i.getIntExtra(Alarms.ID, -1);
mKlaxon = new AlarmKlaxon();
mKlaxon.postPlay(this, mAlarmId);
- /* Set the title from the passed in label */
- setTitleFromIntent(i);
-
/* allow next alarm to trigger while this activity is
active */
Alarms.disableSnoozeAlert(AlarmAlert.this);
}
});
+ requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
updateLayout();
}
if (mLabel == null || mLabel.length() == 0) {
mLabel = getString(R.string.default_label);
}
- setTitle(mLabel);
+ TextView title = (TextView) findViewById(R.id.alertTitle);
+ title.setText(mLabel);
}
private void updateSilencedText() {
silenced.setVisibility(View.VISIBLE);
}
+ // This method is overwritten in AlarmAlertFullScreen in order to show a
+ // full activity with the wallpaper as the background.
+ protected View inflateView(LayoutInflater inflater) {
+ return inflater.inflate(R.layout.alarm_alert, null);
+ }
+
private void updateLayout() {
- setContentView(R.layout.alarm_alert);
+ LayoutInflater inflater = LayoutInflater.from(this);
+
+ setContentView(inflateView(inflater));
/* set clock face */
- LayoutInflater mFactory = LayoutInflater.from(this);
SharedPreferences settings =
getSharedPreferences(AlarmClock.PREFERENCES, 0);
int face = settings.getInt(AlarmClock.PREF_CLOCK_FACE, 0);
if (face < 0 || face >= AlarmClock.CLOCKS.length) {
face = 0;
}
- View clockLayout =
- (View) mFactory.inflate(AlarmClock.CLOCKS[face], null);
ViewGroup clockView = (ViewGroup) findViewById(R.id.clockView);
- clockView.addView(clockLayout);
+ inflater.inflate(AlarmClock.CLOCKS[face], clockView);
+ View clockLayout = findViewById(R.id.clock);
if (clockLayout instanceof DigitalClock) {
((DigitalClock) clockLayout).setAnimate();
}
finish();
}
});
+
+ /* Set the title from the passed in label */
+ setTitleFromIntent(getIntent());
}
// Attempt to snooze this alert.
protected void onResume() {
super.onResume();
if (Log.LOGV) Log.v("AlarmAlert.onResume()");
+ // Acquire a separate lock for the screen to stay on. This is necessary
+ // to avoid flashing the keyguard when the screen is locked.
+ AlarmAlertWakeLock.acquireScreenWakeLock(this);
}
@Override
}
@Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- updateLayout();
- }
-
- @Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Do this on key down to handle a few of the system keys. Only handle
// the snooze and dismiss this alert if the state is unknown.
--- /dev/null
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alarmclock;
+
+import android.graphics.drawable.BitmapDrawable;
+import android.view.View;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+
+/**
+ * Full screen alarm alert: pops visible indicator and plays alarm tone. This
+ * activity displays the alert in full screen in order to be secure. The
+ * background is the current wallpaper.
+ */
+public class AlarmAlertFullScreen extends AlarmAlert {
+
+ @Override
+ final protected View inflateView(LayoutInflater inflater) {
+ View v = inflater.inflate(R.layout.alarm_alert, null);
+
+ // Display the wallpaper as the background.
+ BitmapDrawable wallpaper = (BitmapDrawable) getWallpaper();
+ wallpaper.setGravity(Gravity.CENTER);
+ v.setBackgroundDrawable(wallpaper);
+
+ return v;
+ }
+
+}
*/
class AlarmAlertWakeLock {
- private static PowerManager.WakeLock sWakeLock;
+ private static PowerManager.WakeLock sScreenWakeLock;
+ private static PowerManager.WakeLock sCpuWakeLock;
- static void acquire(Context context) {
- Log.v("Acquiring wake lock");
- if (sWakeLock != null) {
- sWakeLock.release();
+ static void acquireCpuWakeLock(Context context) {
+ Log.v("Acquiring cpu wake lock");
+ if (sCpuWakeLock != null) {
+ return;
}
PowerManager pm =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
- sWakeLock = pm.newWakeLock(
+ sCpuWakeLock = pm.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK |
+ PowerManager.ACQUIRE_CAUSES_WAKEUP |
+ PowerManager.ON_AFTER_RELEASE, Log.LOGTAG);
+ sCpuWakeLock.acquire();
+ }
+
+ static void acquireScreenWakeLock(Context context) {
+ Log.v("Acquiring screen wake lock");
+ if (sScreenWakeLock != null) {
+ return;
+ }
+
+ PowerManager pm =
+ (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+ sScreenWakeLock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, Log.LOGTAG);
- sWakeLock.acquire();
+ sScreenWakeLock.acquire();
}
static void release() {
Log.v("Releasing wake lock");
- if (sWakeLock != null) {
- sWakeLock.release();
- sWakeLock = null;
+ if (sCpuWakeLock != null) {
+ sCpuWakeLock.release();
+ sCpuWakeLock = null;
+ }
+ if (sScreenWakeLock != null) {
+ sScreenWakeLock.release();
+ sScreenWakeLock = null;
}
}
}
if (mClock != null) {
mClockLayout.removeView(mClock);
}
- mClock = mFactory.inflate(CLOCKS[mFace], null);
- TextView am = (TextView) mClock.findViewById(R.id.am);
- TextView pm = (TextView) mClock.findViewById(R.id.pm);
+ LayoutInflater.from(this).inflate(CLOCKS[mFace], mClockLayout);
+ mClock = findViewById(R.id.clock);
+
+ TextView am = (TextView) findViewById(R.id.am);
+ TextView pm = (TextView) findViewById(R.id.pm);
if (am != null) {
am.setText(mAm);
if (pm != null) {
pm.setText(mPm);
}
-
- mClockLayout.addView(mClock, 0);
}
@Override
package com.android.alarmclock;
+import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.BroadcastReceiver;
/* Wake the device and stay awake until the AlarmAlert intent is
* handled. */
- AlarmAlertWakeLock.acquire(context);
+ AlarmAlertWakeLock.acquireCpuWakeLock(context);
/* Close dialogs and window shade */
Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.sendBroadcast(i);
+ // Decide which activity to start based on the state of the keyguard.
+ Class c = AlarmAlert.class;
+ KeyguardManager km = (KeyguardManager) context.getSystemService(
+ Context.KEYGUARD_SERVICE);
+ if (km.inKeyguardRestrictedInputMode()) {
+ // Use the full screen activity for security.
+ c = AlarmAlertFullScreen.class;
+ }
+
/* launch UI, explicitly stating that this is not due to user action
* so that the current app's notification management is not disturbed */
- Intent fireAlarm = new Intent(context, AlarmAlert.class);
+ Intent fireAlarm = new Intent(context, c);
fireAlarm.putExtra(Alarms.ID, id);
fireAlarm.putExtra(Alarms.LABEL, intent.getStringExtra(Alarms.LABEL));
fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
mAttached = true;
if (mAnimate) {
- AnimationDrawable frameAnimation =
- (AnimationDrawable) mContext.getResources().getDrawable(
- R.drawable.animate_circle);
- View digitalClock = findViewById(R.id.digitalClock);
- digitalClock.setBackgroundDrawable(frameAnimation);
+ setBackgroundResource(R.drawable.animate_circle);
/* Start the animation (looped playback by default). */
- ((AnimationDrawable) digitalClock.getBackground()).start();
- /* No luck wrapping animation or individual bitmaps in a
- ScaleDrawable */
- digitalClock.requestLayout();
+ ((AnimationDrawable) getBackground()).start();
}
if (mLive) {