auto import from //depot/cupcake/@132589
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c7a9feb..5a4b2b3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -50,19 +50,5 @@
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
- <receiver android:name=".CalendarGadgetProvider" android:label="@string/gadget_title">
- <intent-filter>
- <action android:name="android.gadget.action.GADGET_UPDATE" />
- <action android:name="com.android.calendar.GADGET_UPDATE" />
- </intent-filter>
- <meta-data android:name="android.gadget.provider" android:resource="@xml/gadget_info" />
- </receiver>
- <receiver android:name=".TimeChangeReceiver" android:enabled="false">
- <intent-filter>
- <action android:name="android.intent.action.TIMEZONE_CHANGED" />
- <action android:name="android.intent.action.TIME_SET" />
- <action android:name="android.intent.action.DATE_CHANGED" />
- </intent-filter>
- </receiver>
</application>
</manifest>
diff --git a/res/drawable/app_icon_blank.png b/res/drawable/app_icon_blank.png
deleted file mode 100644
index 78e4008..0000000
--- a/res/drawable/app_icon_blank.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bg_calendar.9.png b/res/drawable/bg_calendar.9.png
deleted file mode 100644
index 7e9c624..0000000
--- a/res/drawable/bg_calendar.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bg_calendar_primary.9.png b/res/drawable/bg_calendar_primary.9.png
deleted file mode 100644
index 8c3a7c7..0000000
--- a/res/drawable/bg_calendar_primary.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/gadget_date_bg.9.png b/res/drawable/gadget_date_bg.9.png
deleted file mode 100644
index abf4c44..0000000
--- a/res/drawable/gadget_date_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/strip_cal.9.png b/res/drawable/strip_cal.9.png
deleted file mode 100644
index f4cc88d..0000000
--- a/res/drawable/strip_cal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/strip_cal_secondary.9.png b/res/drawable/strip_cal_secondary.9.png
deleted file mode 100644
index acddde0..0000000
--- a/res/drawable/strip_cal_secondary.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/white_list_rule_cal.9.png b/res/drawable/white_list_rule_cal.9.png
deleted file mode 100644
index 0b175a3..0000000
--- a/res/drawable/white_list_rule_cal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-land/gadget_item.xml b/res/layout-land/gadget_item.xml
deleted file mode 100644
index d63eb44..0000000
--- a/res/layout-land/gadget_item.xml
+++ /dev/null
@@ -1,182 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gadget"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="6dip"
- android:background="@drawable/bg_calendar"
- >
-
- <TextView
- android:id="@+id/no_events"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:paddingTop="6dip"
- android:gravity="center"
- android:textStyle="bold"
- android:textSize="16sp"
- android:text="@string/gadget_no_events"
- android:textColor="@color/gadget_no_events"
- />
-
- <FrameLayout
- android:id="@+id/landscape_hidden"
- android:layout_width="0dip"
- android:layout_height="0dip"
- android:visibility="gone"
- >
-
- <TextView
- android:id="@+id/secondary_card"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- <TextView
- android:id="@+id/stub_when"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- <TextView
- android:id="@+id/stub_title"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- <TextView
- android:id="@+id/stub_where"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- <TextView
- android:id="@+id/secondary_when"
- android:layout_width="0dip"
- android:layout_height="0dip"
- android:background="@drawable/strip_cal_secondary"
- />
-
- <TextView
- android:id="@+id/secondary_title"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- <ImageView
- android:id="@+id/divider"
- android:layout_width="0dip"
- android:layout_height="0dip"
- android:background="@drawable/white_list_rule_cal"
- />
-
- <TextView
- android:id="@+id/title2"
- android:layout_width="0dip"
- android:layout_height="0dip"
- />
-
- </FrameLayout>
-
- <RelativeLayout
- android:id="@+id/primary_card"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:paddingLeft="3dip"
- android:paddingRight="3dip"
- android:paddingTop="3dip"
- android:paddingBottom="8dip"
- android:background="@drawable/bg_calendar_primary"
- android:orientation="vertical"
- android:visibility="gone"
- >
-
- <TextView
- android:id="@+id/when"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:paddingTop="1dip"
- android:paddingBottom="1dip"
- android:gravity="center_vertical"
- android:background="@drawable/strip_cal"
- android:textStyle="bold"
- android:textSize="11sp"
- android:textColor="@color/gadget_when"
- android:singleLine="true"
- />
-
- <TextView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/when"
- android:layout_alignParentRight="true"
- android:background="@drawable/gadget_date_bg"
- android:textStyle="bold"
- android:textSize="18sp"
- android:gravity="center"
- android:paddingLeft="8dip"
- android:paddingRight="7dip"
- android:paddingTop="3dip"
- android:paddingBottom="3dip"
- android:layout_marginRight="5dip"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:textColor="#59b4f4"
- android:shadowColor="#ffff"
- android:shadowRadius="2.75"
- android:minWidth="32dip"
- />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@id/when"
- android:layout_toLeftOf="@id/icon"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:textStyle="bold"
- android:textSize="16sp"
- android:textColor="@color/gadget_title"
- android:singleLine="true"
- />
-
- <TextView
- android:id="@+id/where"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/title"
- android:layout_toLeftOf="@id/icon"
- android:layout_alignParentLeft="true"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:textSize="11sp"
- android:textColor="@color/gadget_where"
- android:singleLine="true"
- />
-
- </RelativeLayout>
-
-</RelativeLayout>
-
diff --git a/res/layout/gadget_item.xml b/res/layout/gadget_item.xml
deleted file mode 100644
index e888089..0000000
--- a/res/layout/gadget_item.xml
+++ /dev/null
@@ -1,216 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gadget"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="6dip"
- android:background="@drawable/bg_calendar"
- >
-
- <TextView
- android:id="@+id/no_events"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:paddingTop="6dip"
- android:gravity="center"
- android:textStyle="bold"
- android:textSize="16sp"
- android:text="@string/gadget_no_events"
- android:textColor="@color/gadget_no_events"
- />
-
- <LinearLayout
- android:id="@+id/secondary_card"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="3dip"
- android:layout_marginRight="3dip"
- android:orientation="vertical"
- android:visibility="gone"
- >
-
- <TextView
- android:id="@+id/stub_when"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textStyle="bold"
- android:textSize="11sp"
- android:paddingTop="8dip"
- android:visibility="invisible"
- />
-
- <TextView
- android:id="@+id/stub_title"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textStyle="bold"
- android:textSize="16sp"
- android:visibility="invisible"
- />
-
- <TextView
- android:id="@+id/stub_where"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="11sp"
- android:visibility="invisible"
- />
-
- <TextView
- android:id="@+id/secondary_when"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingTop="1dip"
- android:paddingBottom="1dip"
- android:gravity="center_vertical"
- android:background="@drawable/strip_cal_secondary"
- android:textStyle="bold"
- android:textSize="11sp"
- android:textColor="@color/gadget_when"
- android:singleLine="true"
- />
-
- <TextView
- android:id="@+id/secondary_title"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:textSize="11sp"
- android:textColor="@color/gadget_title"
- android:singleLine="true"
- />
-
- </LinearLayout>
-
- <RelativeLayout
- android:id="@+id/primary_card"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:paddingLeft="3dip"
- android:paddingRight="3dip"
- android:paddingTop="3dip"
- android:paddingBottom="8dip"
- android:background="@drawable/bg_calendar_primary"
- android:orientation="vertical"
- android:visibility="gone"
- >
-
- <TextView
- android:id="@+id/when"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:paddingTop="1dip"
- android:paddingBottom="1dip"
- android:gravity="center_vertical"
- android:background="@drawable/strip_cal"
- android:textStyle="bold"
- android:textSize="11sp"
- android:textColor="@color/gadget_when"
- android:singleLine="true"
- />
-
- <TextView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/when"
- android:layout_alignParentRight="true"
- android:background="@drawable/gadget_date_bg"
- android:textStyle="bold"
- android:textSize="18sp"
- android:gravity="center"
- android:paddingLeft="8dip"
- android:paddingRight="7dip"
- android:paddingTop="3dip"
- android:paddingBottom="3dip"
- android:layout_marginRight="5dip"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:textColor="#59b4f4"
- android:shadowColor="#ffff"
- android:shadowRadius="2.75"
- android:minWidth="32dip"
- />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@id/when"
- android:layout_toLeftOf="@id/icon"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:textStyle="bold"
- android:textSize="16sp"
- android:textColor="@color/gadget_title"
- android:singleLine="true"
- />
-
- <TextView
- android:id="@+id/where"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/title"
- android:layout_toLeftOf="@id/icon"
- android:layout_alignParentLeft="true"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:textSize="11sp"
- android:textColor="@color/gadget_where"
- android:singleLine="true"
- />
-
- <ImageView
- android:id="@+id/divider"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/icon"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="2dip"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:background="@drawable/white_list_rule_cal"
- />
-
- <TextView
- android:id="@+id/title2"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/divider"
- android:layout_alignParentLeft="true"
- android:paddingRight="8dip"
- android:paddingLeft="8dip"
- android:textStyle="bold"
- android:textSize="11sp"
- android:textColor="@color/gadget_title"
- android:singleLine="true"
- />
-
- </RelativeLayout>
-
-</RelativeLayout>
-
diff --git a/res/values/colors.xml b/res/values/colors.xml
deleted file mode 100644
index f6a9f3a..0000000
--- a/res/values/colors.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
- <color name="gadget_when">#ffffffff</color>
- <color name="gadget_reminder">#ffffffff</color>
- <color name="gadget_title">#ff000000</color>
- <color name="gadget_where">#ff000000</color>
- <color name="gadget_calendar">#ff000000</color>
-
- <color name="gadget_no_events">#bb000000</color>
-</resources>
-
diff --git a/res/values/strings.xml b/res/values/strings.xml
deleted file mode 100644
index be90d2e..0000000
--- a/res/values/strings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Title for calendar gadget when displayed in list of all other gadgets -->
- <string name="gadget_title">Calendar</string>
-
- <!-- Title of event when no explicit title is specified by the user -->
- <string name="no_title_label">(No subject)</string>
-
- <!-- Shown in gadget when additional events are available for display, but no room remaining -->
- <plurals name="gadget_more_events">
- <!-- additional events message for 1 event -->
- <item quantity="one">1 more event</item>
- <!-- additional events message for multiple events -->
- <item quantity="other"><xliff:g id="number">%d</xliff:g> more events</item>
- </plurals>
-
- <!-- Caption to show on gadget when there are no upcoming calendar events -->
- <string name="gadget_no_events">No upcoming calendar events</string>
-
-</resources>
diff --git a/res/xml/gadget_info.xml b/res/xml/gadget_info.xml
deleted file mode 100644
index 317384a..0000000
--- a/res/xml/gadget_info.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="294dip"
- android:minHeight="72dip"
- android:updatePeriodMillis="0"
- android:initialLayout="@layout/gadget_item"
- >
-</gadget-provider>
diff --git a/src/com/android/providers/calendar/CalendarGadgetProvider.java b/src/com/android/providers/calendar/CalendarGadgetProvider.java
deleted file mode 100644
index 9afcade..0000000
--- a/src/com/android/providers/calendar/CalendarGadgetProvider.java
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * 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.providers.calendar;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.gadget.GadgetManager;
-import android.gadget.GadgetProvider;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.net.Uri;
-import android.provider.Calendar.Attendees;
-import android.provider.Calendar.Calendars;
-import android.provider.Calendar.Instances;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-import android.text.format.Time;
-import android.util.Log;
-import android.view.View;
-import android.widget.RemoteViews;
-
-import java.util.TimeZone;
-
-/**
- * Simple gadget to show next upcoming calendar event.
- */
-public class CalendarGadgetProvider extends GadgetProvider {
- static final String TAG = "CalendarGadgetProvider";
- static final boolean LOGD = true;
-
- static final String EVENT_SORT_ORDER = "startDay ASC, allDay DESC, begin ASC";
-
- static final String[] EVENT_PROJECTION = new String[] {
- Instances.ALL_DAY,
- Instances.BEGIN,
- Instances.END,
- Instances.COLOR,
- Instances.TITLE,
- Instances.RRULE,
- Instances.HAS_ALARM,
- Instances.EVENT_LOCATION,
- Instances.CALENDAR_ID,
- Instances.EVENT_ID,
- };
-
- static final int INDEX_ALL_DAY = 0;
- static final int INDEX_BEGIN = 1;
- static final int INDEX_END = 2;
- static final int INDEX_COLOR = 3;
- static final int INDEX_TITLE = 4;
- static final int INDEX_RRULE = 5;
- static final int INDEX_HAS_ALARM = 6;
- static final int INDEX_EVENT_LOCATION = 7;
- static final int INDEX_CALENDAR_ID = 8;
- static final int INDEX_EVENT_ID = 9;
-
- static final long SEARCH_DURATION = DateUtils.WEEK_IN_MILLIS;
-
- static final long UPDATE_NO_EVENTS = DateUtils.HOUR_IN_MILLIS * 6;
-
- static final String ACTION_CALENDAR_GADGET_UPDATE = "com.android.calendar.GADGET_UPDATE";
-
- static final String PACKAGE_DETAIL = "com.android.calendar";
- static final String CLASS_DETAIL = "com.android.calendar.AgendaActivity";
-
- static final ComponentName THIS_GADGET =
- new ComponentName("com.android.providers.calendar",
- "com.android.providers.calendar.CalendarGadgetProvider");
-
- private static CalendarGadgetProvider sInstance;
-
- static synchronized CalendarGadgetProvider getInstance() {
- if (sInstance == null) {
- sInstance = new CalendarGadgetProvider();
- }
- return sInstance;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- // Handle calendar-specific updates ourselves because they might be
- // coming in without extras, which GadgetProvider then blocks.
- final String action = intent.getAction();
- if (ACTION_CALENDAR_GADGET_UPDATE.equals(action)) {
- performUpdate(context, null, -1);
- } else {
- super.onReceive(context, intent);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onEnabled(Context context) {
- // Enable updates for timezone and date changes
- PackageManager pm = context.getPackageManager();
- pm.setComponentEnabledSetting(
- new ComponentName(context, TimeChangeReceiver.class),
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onDisabled(Context context) {
- // Unsubscribe from all AlarmManager updates
- AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingUpdate = getUpdateIntent(context);
- am.cancel(pendingUpdate);
-
- // Disable updates for timezone and date changes
- PackageManager pm = context.getPackageManager();
- pm.setComponentEnabledSetting(
- new ComponentName(context, TimeChangeReceiver.class),
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) {
- performUpdate(context, gadgetIds, -1);
- }
-
- /**
- * Check against {@link GadgetManager} if there are any instances of this gadget.
- */
- private boolean hasInstances(Context context) {
- GadgetManager gadgetManager = GadgetManager.getInstance(context);
- int[] gadgetIds = gadgetManager.getGadgetIds(THIS_GADGET);
- return (gadgetIds.length > 0);
- }
-
- /**
- * The {@link CalendarProvider} has been updated, which means we should push
- * updates to any gadgets, if they exist.
- *
- * @param changedEventId Specific event known to be changed, otherwise -1.
- * If present, we use it to decide if an update is necessary.
- */
- void providerUpdated(Context context, long changedEventId) {
- if (hasInstances(context)) {
- performUpdate(context, null, changedEventId);
- }
- }
-
- /**
- * {@link TimeChangeReceiver} has triggered that the time changed.
- */
- void timeUpdated(Context context) {
- if (hasInstances(context)) {
- performUpdate(context, null, -1);
- }
- }
-
- /**
- * Process and push out an update for the given gadgetIds.
- *
- * @param context Context to use when creating gadget.
- * @param gadgetIds List of specific gadgetIds to update, or null for all.
- * @param changedEventId Specific event known to be changed, otherwise -1.
- * If present, we use it to decide if an update is necessary.
- */
- private void performUpdate(Context context, int[] gadgetIds, long changedEventId) {
- ContentResolver resolver = context.getContentResolver();
-
- Cursor cursor = null;
- RemoteViews views = null;
- long triggerTime = -1;
-
- try {
- cursor = getUpcomingInstancesCursor(resolver, SEARCH_DURATION);
- if (cursor != null) {
- MarkedEvents events = buildMarkedEvents(cursor, changedEventId);
-
- boolean shouldUpdate = true;
- if (changedEventId != -1) {
- shouldUpdate = events.watchFound;
- }
-
- if (events.primaryCount == 0) {
- views = getGadgetNoEvents(context);
- } else if (shouldUpdate) {
- views = getGadgetUpdate(context, cursor, events);
- triggerTime = calculateUpdateTime(context, cursor, events);
- }
- } else {
- views = getGadgetNoEvents(context);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- // Bail out early if no update built
- if (views == null) {
- if (LOGD) Log.d(TAG, "Didn't build update, possibly because changedEventId=" + changedEventId);
- return;
- }
-
- GadgetManager gm = GadgetManager.getInstance(context);
- if (gadgetIds != null) {
- gm.updateGadget(gadgetIds, views);
- } else {
- ComponentName thisGadget = new ComponentName(context, CalendarGadgetProvider.class);
- gm.updateGadget(thisGadget, views);
- }
-
- // Schedule an alarm to wake ourselves up for the next update. We also cancel
- // all existing wake-ups because PendingIntents don't match against extras.
-
- // If no next-update calculated, or bad trigger time in past, schedule
- // update about six hours from now.
- long now = System.currentTimeMillis();
- if (triggerTime == -1 || triggerTime < now) {
- if (LOGD) Log.w(TAG, "Encountered bad trigger time " + formatDebugTime(triggerTime));
- triggerTime = now + UPDATE_NO_EVENTS;
- }
-
- AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pendingUpdate = getUpdateIntent(context);
-
- am.cancel(pendingUpdate);
- am.set(AlarmManager.RTC, triggerTime, pendingUpdate);
-
- if (LOGD) Log.d(TAG, "Scheduled next update at " + formatDebugTime(triggerTime));
- }
-
- /**
- * Build the {@link PendingIntent} used to trigger an update of all calendar
- * gadgets. Uses {@link ACTION_CALENDAR_GADGET_UPDATE} to directly target
- * all gadgets instead of using {@link GadgetManager#EXTRA_GADGET_IDS}.
- */
- private PendingIntent getUpdateIntent(Context context) {
- Intent updateIntent = new Intent(ACTION_CALENDAR_GADGET_UPDATE);
- updateIntent.setComponent(new ComponentName(context, CalendarGadgetProvider.class));
- return PendingIntent.getBroadcast(context, 0 /* no requestCode */,
- updateIntent, 0 /* no flags */);
- }
-
- /**
- * Format given time for debugging output.
- */
- private String formatDebugTime(long unixTime) {
- Time time = new Time();
- time.set(unixTime);
-
- long delta = unixTime - System.currentTimeMillis();
- if (delta > DateUtils.MINUTE_IN_MILLIS) {
- delta /= DateUtils.MINUTE_IN_MILLIS;
- return String.format("[%d] %s (%+d mins)", unixTime, time.format("%H:%M:%S"), delta);
- } else {
- delta /= DateUtils.SECOND_IN_MILLIS;
- return String.format("[%d] %s (%+d secs)", unixTime, time.format("%H:%M:%S"), delta);
- }
- }
-
- /**
- * Convert given UTC time into current local time.
- *
- * @param recycle Time object to recycle, otherwise null.
- * @param utcTime Time to convert, in UTC.
- */
- private long convertUtcToLocal(Time recycle, long utcTime) {
- if (recycle == null) {
- recycle = new Time();
- }
- recycle.timezone = Time.TIMEZONE_UTC;
- recycle.set(utcTime);
- recycle.timezone = TimeZone.getDefault().getID();
- return recycle.normalize(true);
- }
-
- /**
- * Figure out the next time we should push gadget updates. This is based on
- * the time calculated by {@link #getEventFlip(Cursor, int)}.
- */
- private long calculateUpdateTime(Context context, Cursor cursor, MarkedEvents events) {
- long result = -1;
- if (events.primaryRow != -1) {
- cursor.moveToPosition(events.primaryRow);
- long start = cursor.getLong(INDEX_BEGIN);
- long end = cursor.getLong(INDEX_END);
- boolean allDay = cursor.getInt(INDEX_ALL_DAY) != 0;
-
- // Adjust all-day times into local timezone
- if (allDay) {
- final Time recycle = new Time();
- start = convertUtcToLocal(recycle, start);
- end = convertUtcToLocal(recycle, end);
- }
-
- result = getEventFlip(cursor, start, end, allDay);
- }
- return result;
- }
-
- /**
- * Calculate flipping point for the given event; when we should hide this
- * event and show the next one. This is usually half-way through the event.
- *
- * @param start Event start time in local timezone.
- * @param end Event end time in local timezone.
- */
- private long getEventFlip(Cursor cursor, long start, long end, boolean allDay) {
- if (allDay) {
- return start;
- } else {
- return (start + end) / 2;
- }
- }
-
- /**
- * Build a set of {@link RemoteViews} that describes how to update any
- * gadget for a specific event instance.
- *
- * @param cursor Valid cursor on {@link Instances#CONTENT_URI}
- * @param events {@link MarkedEvents} parsed from the cursor
- */
- private RemoteViews getGadgetUpdate(Context context, Cursor cursor, MarkedEvents events) {
- Resources res = context.getResources();
- ContentResolver resolver = context.getContentResolver();
-
- RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gadget_item);
-
- // Clicking on gadget launches the agenda view in Calendar
- Intent agendaIntent = new Intent();
- agendaIntent.setComponent(new ComponentName(PACKAGE_DETAIL, CLASS_DETAIL));
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */,
- agendaIntent, 0 /* no flags */);
-
- views.setOnClickPendingIntent(R.id.gadget, pendingIntent);
-
- Time time = new Time();
- time.setToNow();
- int yearDay = time.yearDay;
- int dateNumber = time.monthDay;
-
- // Set calendar icon with actual date
- views.setTextViewText(R.id.icon, Integer.toString(dateNumber));
- views.setViewVisibility(R.id.icon, View.VISIBLE);
- views.setViewVisibility(R.id.no_events, View.GONE);
-
- // Fill primary event details
- if (events.primaryRow != -1) {
- views.setViewVisibility(R.id.primary_card, View.VISIBLE);
- cursor.moveToPosition(events.primaryRow);
-
- // Color stripe
- int colorFilter = cursor.getInt(INDEX_COLOR);
- views.setDrawableParameters(R.id.when, true, -1, colorFilter,
- PorterDuff.Mode.SRC_IN, -1);
- views.setTextColor(R.id.title, colorFilter);
- views.setTextColor(R.id.where, colorFilter);
- views.setDrawableParameters(R.id.divider, true, -1, colorFilter,
- PorterDuff.Mode.SRC_IN, -1);
- views.setTextColor(R.id.title2, colorFilter);
-
- // When
- long start = cursor.getLong(INDEX_BEGIN);
- boolean allDay = cursor.getInt(INDEX_ALL_DAY) != 0;
-
- int flags;
- String whenString;
- if (allDay) {
- flags = DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_UTC
- | DateUtils.FORMAT_SHOW_DATE;
- } else {
- flags = DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_TIME;
-
- // Show date if different from today
- time.set(start);
- if (yearDay != time.yearDay) {
- flags = flags | DateUtils.FORMAT_SHOW_DATE;
- }
- }
- if (DateFormat.is24HourFormat(context)) {
- flags |= DateUtils.FORMAT_24HOUR;
- }
- whenString = DateUtils.formatDateRange(context, start, start, flags);
- views.setTextViewText(R.id.when, whenString);
-
- // What
- String titleString = cursor.getString(INDEX_TITLE);
- if (titleString == null || titleString.length() == 0) {
- titleString = context.getString(R.string.no_title_label);
- }
- views.setTextViewText(R.id.title, titleString);
-
- // Where
- String whereString = cursor.getString(INDEX_EVENT_LOCATION);
- if (whereString != null && whereString.length() > 0) {
- views.setViewVisibility(R.id.where, View.VISIBLE);
- views.setViewVisibility(R.id.stub_where, View.INVISIBLE);
- views.setTextViewText(R.id.where, whereString);
- } else {
- views.setViewVisibility(R.id.where, View.GONE);
- views.setViewVisibility(R.id.stub_where, View.GONE);
- }
- }
-
- // Fill other primary events, if present
- if (events.primaryConflictRow != -1) {
- views.setViewVisibility(R.id.divider, View.VISIBLE);
- views.setViewVisibility(R.id.title2, View.VISIBLE);
-
- if (events.primaryCount > 2) {
- // If more than two primary conflicts, format multiple message
- int count = events.primaryCount - 1;
- String titleString = String.format(res.getQuantityString(
- R.plurals.gadget_more_events, count), count);
- views.setTextViewText(R.id.title2, titleString);
- } else {
- cursor.moveToPosition(events.primaryConflictRow);
-
- // What
- String titleString = cursor.getString(INDEX_TITLE);
- if (titleString == null || titleString.length() == 0) {
- titleString = context.getString(R.string.no_title_label);
- }
- views.setTextViewText(R.id.title2, titleString);
- }
- } else {
- views.setViewVisibility(R.id.divider, View.GONE);
- views.setViewVisibility(R.id.title2, View.GONE);
- }
-
- // Fill secondary event
- if (events.secondaryRow != -1) {
- views.setViewVisibility(R.id.secondary_card, View.VISIBLE);
- views.setViewVisibility(R.id.secondary_when, View.VISIBLE);
- views.setViewVisibility(R.id.secondary_title, View.VISIBLE);
-
- cursor.moveToPosition(events.secondaryRow);
-
- // Color stripe
- int colorFilter = cursor.getInt(INDEX_COLOR);
- views.setDrawableParameters(R.id.secondary_when, true, -1, colorFilter,
- PorterDuff.Mode.SRC_IN, -1);
- views.setTextColor(R.id.secondary_title, colorFilter);
-
- // When
- long start = cursor.getLong(INDEX_BEGIN);
- boolean allDay = cursor.getInt(INDEX_ALL_DAY) != 0;
-
- int flags;
- String whenString;
- if (allDay) {
- flags = DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_UTC
- | DateUtils.FORMAT_SHOW_DATE;
- } else {
- flags = DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_TIME;
-
- // Show date if different from today
- time.set(start);
- if (yearDay != time.yearDay) {
- flags = flags | DateUtils.FORMAT_SHOW_DATE;
- }
- }
- if (DateFormat.is24HourFormat(context)) {
- flags |= DateUtils.FORMAT_24HOUR;
- }
- whenString = DateUtils.formatDateRange(context, start, start, flags);
- views.setTextViewText(R.id.secondary_when, whenString);
-
- if (events.secondaryCount > 1) {
- // If more than two secondary conflicts, format multiple message
- int count = events.secondaryCount;
- String titleString = String.format(res.getQuantityString(
- R.plurals.gadget_more_events, count), count);
- views.setTextViewText(R.id.secondary_title, titleString);
- } else {
- // What
- String titleString = cursor.getString(INDEX_TITLE);
- if (titleString == null || titleString.length() == 0) {
- titleString = context.getString(R.string.no_title_label);
- }
- views.setTextViewText(R.id.secondary_title, titleString);
- }
- } else {
- views.setViewVisibility(R.id.secondary_when, View.GONE);
- views.setViewVisibility(R.id.secondary_title, View.GONE);
- }
-
- return views;
- }
-
- /**
- * Build a set of {@link RemoteViews} that describes an error state.
- */
- private RemoteViews getGadgetNoEvents(Context context) {
- RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gadget_item);
-
- views.setViewVisibility(R.id.no_events, View.VISIBLE);
-
- views.setViewVisibility(R.id.primary_card, View.GONE);
- views.setViewVisibility(R.id.secondary_card, View.GONE);
-
- // Clicking on gadget launches the agenda view in Calendar
- Intent agendaIntent = new Intent();
- agendaIntent.setComponent(new ComponentName(PACKAGE_DETAIL, CLASS_DETAIL));
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */,
- agendaIntent, 0 /* no flags */);
-
- views.setOnClickPendingIntent(R.id.gadget, pendingIntent);
-
- return views;
- }
-
- private static class MarkedEvents {
- long primaryTime = -1;
- int primaryRow = -1;
- int primaryConflictRow = -1;
- int primaryCount = 0;
- long secondaryTime = -1;
- int secondaryRow = -1;
- int secondaryCount = 0;
- boolean watchFound = false;
- }
-
- /**
- * Walk the given instances cursor and build a list of marked events to be
- * used when updating the gadget. This structure is also used to check if
- * updates are needed.
- *
- * @param cursor Valid cursor across {@link Instances#CONTENT_URI}.
- * @param watchEventId Specific event to watch for, setting
- * {@link MarkedEvents#watchFound} if found during marking.
- */
- private MarkedEvents buildMarkedEvents(Cursor cursor, long watchEventId) {
- MarkedEvents events = new MarkedEvents();
- long now = System.currentTimeMillis();
- final Time recycle = new Time();
-
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- int row = cursor.getPosition();
- long eventId = cursor.getLong(INDEX_EVENT_ID);
- long start = cursor.getLong(INDEX_BEGIN);
- long end = cursor.getLong(INDEX_END);
- boolean allDay = cursor.getInt(INDEX_ALL_DAY) != 0;
-
- // Adjust all-day times into local timezone
- if (allDay) {
- start = convertUtcToLocal(recycle, start);
- end = convertUtcToLocal(recycle, end);
- }
-
- // Skip events that have already passed their flip times
- long eventFlip = getEventFlip(cursor, start, end, allDay);
- if (LOGD) Log.d(TAG, "Calculated flip time " + formatDebugTime(eventFlip));
- if (eventFlip < now) {
- continue;
- }
-
- // Mark if we've encountered the watched event
- if (eventId == watchEventId) {
- events.watchFound = true;
- }
-
- if (events.primaryRow == -1) {
- // Found first event
- events.primaryRow = row;
- events.primaryTime = start;
- events.primaryCount = 1;
- } else if (events.primaryTime == start) {
- // Found conflicting primary event
- if (events.primaryConflictRow == -1) {
- events.primaryConflictRow = row;
- }
- events.primaryCount += 1;
- } else if (events.secondaryRow == -1) {
- // Found second event
- events.secondaryRow = row;
- events.secondaryTime = start;
- events.secondaryCount = 1;
- } else if (events.secondaryTime == start) {
- // Found conflicting secondary event
- events.secondaryCount += 1;
- } else {
- // Nothing interesting about this event, so bail out
- break;
- }
- }
- return events;
- }
-
- /**
- * Query across all calendars for upcoming event instances from now until
- * some time in the future.
- *
- * @param searchDuration Distance into the future to look for event
- * instances, in milliseconds.
- */
- private Cursor getUpcomingInstancesCursor(ContentResolver resolver, long searchDuration) {
- // Search for events from now until some time in the future
- long start = System.currentTimeMillis();
- long end = start + searchDuration;
-
- Uri uri = Uri.withAppendedPath(Instances.CONTENT_URI,
- String.format("%d/%d", start, end));
-
- String selection = String.format("%s=1 AND %s!=%d",
- Calendars.SELECTED, Instances.SELF_ATTENDEE_STATUS,
- Attendees.ATTENDEE_STATUS_DECLINED);
-
- return resolver.query(uri, EVENT_PROJECTION, selection, null,
- EVENT_SORT_ORDER);
- }
-
-}
diff --git a/src/com/android/providers/calendar/CalendarProvider.java b/src/com/android/providers/calendar/CalendarProvider.java
index a053a15..5fe0998 100644
--- a/src/com/android/providers/calendar/CalendarProvider.java
+++ b/src/com/android/providers/calendar/CalendarProvider.java
@@ -180,17 +180,15 @@
// A thread that runs in the background and schedules the next
// calendar event alarm.
- private class AlarmScheduler extends Thread {
- boolean mRemoveAlarms;
-
- public AlarmScheduler(boolean removeAlarms) {
- mRemoveAlarms = removeAlarms;
+ private class AlarmScheduler implements Runnable {
+
+ public AlarmScheduler() {
}
public void run() {
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- runScheduleNextAlarm(mRemoveAlarms);
+ runScheduleNextAlarm();
} catch (SQLException e) {
Log.e(TAG, "runScheduleNextAlarm() failed", e);
}
@@ -272,7 +270,6 @@
private AlarmManager mAlarmManager;
private CalendarSyncAdapter mSyncAdapter;
- private CalendarGadgetProvider mGadgetProvider = CalendarGadgetProvider.getInstance();
/**
* Listens for timezone changes and disk-no-longer-full events
@@ -286,13 +283,13 @@
}
if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
updateTimezoneDependentFields();
- scheduleNextAlarm(false /* do not remove alarms */);
+ scheduleNextAlarm();
} else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
// Try to clean up if things were screwy due to a full disk
updateTimezoneDependentFields();
- scheduleNextAlarm(false /* do not remove alarms */);
+ scheduleNextAlarm();
} else if (Intent.ACTION_TIME_CHANGED.equals(action)) {
- scheduleNextAlarm(false /* do not remove alarms */);
+ scheduleNextAlarm();
}
}
};
@@ -2411,7 +2408,6 @@
int status = initialValues.getAsInteger(Events.SELF_ATTENDEE_STATUS);
createAttendeeEntry(rowId, status);
}
- triggerGadgetUpdate(rowId);
}
return uri;
@@ -2459,7 +2455,7 @@
if (DEBUG_ALARMS) {
Log.i(TAG, "insertInternal() changing reminder");
}
- scheduleNextAlarm(false /* do not remove alarms */);
+ scheduleNextAlarm();
}
return Uri.parse("content://calendars/reminders/" + rowID);
case CALENDAR_ALERTS:
@@ -2938,7 +2934,6 @@
cursor.close();
cursor = null;
}
- triggerGadgetUpdate(-1);
}
// There is a delete trigger that will cause all instances
@@ -3107,8 +3102,7 @@
if (DEBUG_ALARMS) {
Log.i(TAG, "updateInternal() changing event");
}
- scheduleNextAlarm(false /* do not remove alarms */);
- triggerGadgetUpdate(id);
+ scheduleNextAlarm();
}
}
}
@@ -3137,7 +3131,7 @@
if (DEBUG_ALARMS) {
Log.i(TAG, "updateInternal() changing reminder");
}
- scheduleNextAlarm(false /* do not remove alarms */);
+ scheduleNextAlarm();
}
return result;
}
@@ -3258,37 +3252,13 @@
if (DEBUG_ALARMS) {
Log.i(TAG, "onSyncStop() success: " + success);
}
- scheduleNextAlarm(false /* do not remove alarms */);
- triggerGadgetUpdate(-1);
+ scheduleNextAlarm();
}
@Override
protected Iterable<EventMerger> getMergers() {
return Collections.singletonList(new EventMerger());
}
-
- /**
- * Update any existing gadgets with the changed events.
- *
- * @param changedEventId Specific event known to be changed, otherwise -1.
- * If present, we use it to decide if an update is necessary.
- */
- private synchronized void triggerGadgetUpdate(long changedEventId) {
- Context context = getContext();
- if (context != null) {
- mGadgetProvider.providerUpdated(context, changedEventId);
- }
- }
-
- void bootCompleted() {
- // Remove alarms from the CalendarAlerts table that have been marked
- // as "scheduled" but not fired yet. We do this because the
- // AlarmManagerService loses all information about alarms when the
- // power turns off but we store the information in a database table
- // that persists across reboots. See the documentation for
- // scheduleNextAlarmLocked() for more information.
- scheduleNextAlarm(true /* remove alarms */);
- }
/* Retrieve and cache the alarm manager */
private AlarmManager getAlarmManager() {
@@ -3340,8 +3310,8 @@
/*
* This method runs the alarm scheduler in a background thread.
*/
- void scheduleNextAlarm(boolean removeAlarms) {
- Thread thread = new AlarmScheduler(removeAlarms);
+ void scheduleNextAlarm() {
+ Thread thread = new Thread(new AlarmScheduler());
thread.start();
}
@@ -3349,8 +3319,9 @@
* This method runs in a background thread and schedules an alarm for
* the next calendar event, if necessary.
*/
- private void runScheduleNextAlarm(boolean removeAlarms) {
- // Do not schedule any alarms if this is a temporary database.
+ private void runScheduleNextAlarm() {
+ // Do not schedule any events while syncing or if this is a temporary
+ // database.
if (isTemporary()) {
if (DEBUG_ALARMS) {
Log.i(TAG, "runScheduleNextAlarm cancelled because database is temporary");
@@ -3361,9 +3332,6 @@
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
- if (removeAlarms) {
- removeScheduledAlarmsLocked(db);
- }
scheduleNextAlarmLocked(db);
db.setTransactionSuccessful();
} finally {
@@ -3373,27 +3341,7 @@
/**
* This method looks at the 24-hour window from now for any events that it
- * needs to schedule. This method runs within a database transaction. It
- * also runs in a background thread.
- *
- * The CalendarProvider keeps track of which alarms it has already scheduled
- * to avoid scheduling them more than once and for debugging problems with
- * alarms. It stores this knowledge in a database table called CalendarAlerts
- * which persists across reboots. But the actual alarm list is in memory
- * and disappears if the phone loses power. To avoid missing an alarm, we
- * clear the entries in the CalendarAlerts table when we start up the
- * CalendarProvider.
- *
- * Scheduling an alarm multiple times is not tragic -- we filter out the
- * extra ones when we receive them. But we still need to keep track of the
- * scheduled alarms. The main reason is that we need to prevent multiple
- * notifications for the same alarm (on the receive side) in case we
- * accidentally schedule the same alarm multiple times. We don't have
- * visibility into the system's alarm list so we can never know for sure if
- * we have already scheduled an alarm and it's better to err on scheduling
- * an alarm twice rather than missing an alarm. Another reason we keep
- * track of scheduled alarms in a database table is that it makes it easy to
- * run an SQL query to find the next reminder that we haven't scheduled.
+ * needs to schedule. This method runs within a database transaction.
*
* @param db the database
*/
@@ -3460,7 +3408,7 @@
+ " AND CA.alarmTime=myAlarmTime)"
+ " ORDER BY myAlarmTime,begin,title";
- acquireInstanceRangeLocked(start, end, false /* don't use minimum expansion windows */);
+ acquireInstanceRange(start, end, false /* don't use minimum expansion windows */);
Cursor cursor = null;
try {
cursor = db.rawQuery(query, null);
@@ -3476,8 +3424,7 @@
time.set(nextAlarmTime);
String alarmTimeStr = time.format(" %a, %b %d, %Y %I:%M%P");
Log.i(TAG, "nextAlarmTime: " + alarmTimeStr
- + " cursor results: " + cursor.getCount()
- + " query: " + query);
+ + " cursor results: " + cursor.getCount());
}
while (cursor.moveToNext()) {
@@ -3586,30 +3533,6 @@
scheduleNextAlarmCheck(currentMillis + android.text.format.DateUtils.DAY_IN_MILLIS);
}
}
-
- /**
- * Removes the entries in the CalendarAlerts table for alarms that we have
- * scheduled but that have not fired yet. We do this to ensure that we
- * don't miss an alarm. The CalendarAlerts table keeps track of the
- * alarms that we have scheduled but the actual alarm list is in memory
- * and will be cleared if the phone reboots.
- *
- * We don't need to remove entries that have already fired, and in fact
- * we should not remove them because we need to display the notifications
- * until the user dismisses them.
- *
- * We could remove entries that have fired and been dismissed, but we leave
- * them around for a while because it makes it easier to debug problems.
- * Entries that are old enough will be cleaned up later when we schedule
- * new alarms.
- */
- private void removeScheduledAlarmsLocked(SQLiteDatabase db) {
- if (DEBUG_ALARMS) {
- Log.i(TAG, "removing scheduled alarms");
- }
- db.delete(CalendarAlerts.TABLE_NAME,
- CalendarAlerts.STATE + "=" + CalendarAlerts.SCHEDULED, null /* whereArgs */);
- }
private static String sEventsTable = "Events";
private static Uri sEventsURL =
diff --git a/src/com/android/providers/calendar/CalendarReceiver.java b/src/com/android/providers/calendar/CalendarReceiver.java
index 21a1398..f3bef8f 100644
--- a/src/com/android/providers/calendar/CalendarReceiver.java
+++ b/src/com/android/providers/calendar/CalendarReceiver.java
@@ -16,12 +16,12 @@
package com.android.providers.calendar;
-import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
+import android.content.BroadcastReceiver;
/**
* This IntentReceiver executes when the boot completes and ensures that
@@ -43,9 +43,9 @@
provider = (CalendarProvider) ContentProvider.
coerceToLocalContentProvider(icp);
if (action.equals(SCHEDULE)) {
- provider.scheduleNextAlarm(false /* do not remove alarms */);
+ provider.scheduleNextAlarm();
} else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- provider.bootCompleted();
+ provider.scheduleNextAlarm();
}
cr.releaseProvider(icp);
}
diff --git a/src/com/android/providers/calendar/CalendarSyncAdapter.java b/src/com/android/providers/calendar/CalendarSyncAdapter.java
index db278fe..57cb084 100644
--- a/src/com/android/providers/calendar/CalendarSyncAdapter.java
+++ b/src/com/android/providers/calendar/CalendarSyncAdapter.java
@@ -116,7 +116,7 @@
protected CalendarSyncAdapter(Context context, SyncableContentProvider provider) {
super(context, provider);
mCalendarClient = new CalendarClient(
- new AndroidGDataClient(context),
+ new AndroidGDataClient(context.getContentResolver()),
new XmlCalendarGDataParserFactory(new AndroidXmlParserFactory()));
}
diff --git a/src/com/android/providers/calendar/RecurrenceProcessor.java b/src/com/android/providers/calendar/RecurrenceProcessor.java
index 6d68ca2..5edfd6a 100644
--- a/src/com/android/providers/calendar/RecurrenceProcessor.java
+++ b/src/com/android/providers/calendar/RecurrenceProcessor.java
@@ -33,8 +33,6 @@
private StringBuilder mStringBuilder = new StringBuilder();
private Time mGenerated = new Time(Time.TIMEZONE_UTC);
private DaySet mDays = new DaySet(false);
- // Give up after this many loops. This is roughly 1 second of expansion.
- private static final int MAX_ALLOWED_ITERATIONS = 2000;
public RecurrenceProcessor()
{
@@ -741,13 +739,9 @@
boolean eventEnded = false;
int N, i, v;
int a[];
- int failsafe = 0; // Avoid infinite loops
events: {
while (true) {
int monthIndex = 0;
- if (failsafe++ > MAX_ALLOWED_ITERATIONS) { // Give up after about 1 second of processing
- throw new DateException("Recurrence processing stuck: " + r.toString());
- }
unsafeNormalize(iterator);
diff --git a/src/com/android/providers/calendar/TimeChangeReceiver.java b/src/com/android/providers/calendar/TimeChangeReceiver.java
deleted file mode 100644
index 6a7d3c6..0000000
--- a/src/com/android/providers/calendar/TimeChangeReceiver.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.providers.calendar;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-public class TimeChangeReceiver extends BroadcastReceiver {
- static final String TAG = "TimeChangeReceiver";
- static final boolean LOGD = false;
-
- CalendarGadgetProvider mCalendarProvider = CalendarGadgetProvider.getInstance();
-
- @Override
- public void onReceive(Context context, Intent intent) {
- // Pass time-changed notification through to any gadgets
- if (LOGD) Log.d(TAG, "Received time changed action=" + intent.getAction());
- mCalendarProvider.timeUpdated(context);
- }
-}
diff --git a/tests/src/com/android/providers/calendar/ICalendarTest.java b/tests/src/com/android/providers/calendar/ICalendarTest.java
index cedc92e..685d1c9 100644
--- a/tests/src/com/android/providers/calendar/ICalendarTest.java
+++ b/tests/src/com/android/providers/calendar/ICalendarTest.java
@@ -224,49 +224,4 @@
ICalendar.Component component = ICalendar.parseComponent(text);
assertNotNull(component);
}
-
- @SmallTest
- public void testNormalize() throws Exception {
- String text = "BEGIN:VEVENT\n" +
- "RRULE:FREQ=SECONDLY;BYSECOND=0,1,2,\r\n 3,4,5\r\n ,6,7,8\r\n" +
- "END:VEVENT\n";
-
- ICalendar.Component event = ICalendar.parseEvent(text);
-
- assertEquals("VEVENT", event.getName());
- assertNull(event.getComponents());
- assertEquals(1, event.getPropertyNames().size());
- assertEquals(1, event.getProperties("RRULE").size());
- assertEquals("FREQ=SECONDLY;BYSECOND=0,1,2,3,4,5,6,7,8", event.getFirstProperty("RRULE").getValue());
-
- }
-
- @SmallTest
- public void testNormalizeBadSep() throws Exception {
- String text = "BEGIN:VEVENT\n" +
- "RRULE:FREQ=SECONDLY;BYSECOND=0,1,2,\n 3,4,5\n ,6,7,8\n" +
- "END:VEVENT\n";
-
- ICalendar.Component event = ICalendar.parseEvent(text);
-
- assertEquals("VEVENT", event.getName());
- assertNull(event.getComponents());
- assertEquals(1, event.getPropertyNames().size());
- assertEquals(1, event.getProperties("RRULE").size());
- assertEquals("FREQ=SECONDLY;BYSECOND=0,1,2,3,4,5,6,7,8", event.getFirstProperty("RRULE").getValue());
- }
-
-
- @SmallTest
- public void testBad() throws Exception {
- String text = "BEGIN:VEVENT\n" +
- "RRULE=foo\n" +
- "END:VEVENT\n";
-
- ICalendar.Component event = ICalendar.parseEvent(text);
-
- // Note that parseEvent doesn't throw the FormatException you might expect because
- // ICalendar.parseComponentImpl catches the exception due to misformatted GData.
- // TODO: update this test after cleaning up the ICalendar behavior
- }
}
diff --git a/tests/src/com/android/providers/calendar/RRuleTest.java b/tests/src/com/android/providers/calendar/RRuleTest.java
deleted file mode 100644
index f12ec67..0000000
--- a/tests/src/com/android/providers/calendar/RRuleTest.java
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-/* Based on http://code.google.com/p/google-rfc-2445/source/browse/trunk/test/com/google/ical/iter/RRuleIteratorImplTest.java */
-
-package com.android.providers.calendar;
-
-import android.os.Debug;
-import android.pim.DateException;
-import android.pim.RecurrenceSet;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.format.Time;
-import junit.framework.TestCase;
-
-public class RRuleTest extends TestCase {
- private static final String TAG = "RRuleTest";
- private static final boolean METHOD_TRACE = false;
-
- private static String[] getFormattedDates(long[] dates, Time time, boolean truncate) {
- String[] out = new String[dates.length];
- int i = 0;
- for (long date : dates) {
- time.set(date);
- if (truncate) {
- out[i] = time.format2445().substring(0, 8); // Just YYMMDD
- } else {
- out[i] = time.format2445().substring(0, 15); // YYMMDDThhmmss
- }
- ++i;
- }
- return out;
- }
-
- static final String PST = "America/Los_Angeles";
- static final String UTC = "UTC";
- // Use this date as end of recurrence unlessotherwise specified.
- static final String DEFAULT_END = "20091212";
-
- private void runRecurrenceIteratorTest(String rruleText, String dtStart, int limit,
- String golden) throws Exception {
- runRecurrenceIteratorTest(rruleText, dtStart, limit, golden, null, null, UTC);
- }
-
- private void runRecurrenceIteratorTest(String rrule, String dtstartStr, int limit,
- String golden, String advanceTo, String tz) throws Exception {
- runRecurrenceIteratorTest(rrule, dtstartStr, limit, golden, advanceTo, null, tz);
- }
-
- /**
- * Tests a recurrence rule
- * @param rrule The rule to expand
- * @param dtstartStr The dtstart to use
- * @param limit Maximum number of entries to expand. if there are more, "..." is appended to
- * the result. Note that Android's recurrence expansion doesn't support expanding n results,
- * so this is faked by expanding until the endAt date, and then taking limit results.
- * @param golden The desired results
- * @param advanceTo The starting date for expansion. dtstartStr is used if null is passed in.
- * @param endAt The ending date. DEFAULT_END is used if null is passed in.
- * @param tz The time zone. UTC is used if null is passed in.
- * @throws Exception if anything goes wrong.
- */
- private void runRecurrenceIteratorTest(String rrule, String dtstartStr, int limit,
- String golden, String advanceTo, String endAt, String tz) throws Exception {
-
- String rdate = "";
- String exrule = "";
- String exdate = "";
- rrule = rrule.replace("RRULE:", "");
- // RecurrenceSet does not support folding of lines, so fold here
- rrule = rrule.replace("\n ", "");
-
- Time dtstart = new Time(tz);
- Time rangeStart = new Time(tz);
- Time rangeEnd = new Time(tz);
- Time outCal = new Time(tz);
-
- dtstart.parse(dtstartStr);
- if (advanceTo == null) {
- advanceTo = dtstartStr;
- }
- if (endAt == null) {
- endAt = DEFAULT_END;
- }
-
- rangeStart.parse(advanceTo);
- rangeEnd.parse(endAt);
-
-
- RecurrenceProcessor rp = new RecurrenceProcessor();
- RecurrenceSet recur = new RecurrenceSet(rrule, rdate, exrule, exdate);
-
- long[] out = rp.expand(dtstart, recur, rangeStart.toMillis(false /* use isDst */),
- rangeEnd.toMillis(false /* use isDst */));
-
- if (METHOD_TRACE) {
- Debug.stopMethodTracing();
- }
-
- boolean truncate = dtstartStr.length() <= 8; // Just date, not date-time
- String[] actual = getFormattedDates(out, outCal, truncate);
-
- StringBuilder sb = new StringBuilder();
- int k = 0;
- while (k < actual.length && --limit >= 0) {
- if (k != 0) {
- sb.append(',');
- }
- sb.append(actual[k]);
- k++;
- }
- if (limit < 0) {
- sb.append(",...");
- }
- assertEquals(golden, sb.toString());
- }
-
- // Infinite loop, bug 1662110
- @SmallTest
- public void testFrequencyLimits() throws Exception {
- try {
- runRecurrenceIteratorTest("RRULE:FREQ=SECONDLY;BYSECOND=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14," + "15,16,17,18,19,20,21,22,23,24,25,26,27,28,29," + "30,31,32,33,34,35,36,37,38,39,40,41,42,43,44," + "45,46,47,48,49,50,51,52,53,54,55,56,57,58,59", "20000101", 1, "");
- fail("Don't do that");
- } catch (DateException ex) {
- // pass
- }
- }
-
- @SmallTest
- public void testSimpleDaily() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY", "20060120", 5, "20060120,20060121,20060122,20060123,20060124,...");
- }
-
- @SmallTest
- public void testSimpleWeekly() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY", "20060120", 5, "20060120,20060127,20060203,20060210,20060217,...");
- }
-
- @SmallTest
- public void testSimpleMonthly() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY", "20060120", 5, "20060120,20060220,20060320,20060420,20060520,...");
- }
-
- @SmallTest
- public void testSimpleYearly() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY", "20060120", 5, "20060120,20070120,20080120,20090120,20100120,...", null, "20120101", UTC);
- }
-
- // from section 4.3.10
- @SmallTest
- public void testMultipleByParts() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU", "19970105", 8, "19970105,19970112,19970119,19970126," + "19990103,19990110,19990117,19990124,...");
- }
-
- @SmallTest
- public void testCountWithInterval() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;COUNT=10;INTERVAL=2", "19970105", 11, "19970105,19970107,19970109,19970111,19970113," + "19970115,19970117,19970119,19970121,19970123");
- }
-
- // from section 4.6.5
- // Fails: wrong dates
- @SmallTest
- public void failingTestNegativeOffsetsA() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10", "19970105", 5, "19971026,19981025,19991031,20001029,20011028,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestNegativeOffsetsB() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4", "19970105", 5, "19970406,19980405,19990404,20000402,20010401,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestNegativeOffsetsC() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T150000Z", "19970105", 5, "19970406");
- }
-
- // feom section 4.8.5.4
- @SmallTest
- public void testDailyFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;COUNT=10", "19970902T090000", 11, "19970902T090000,19970903T090000,19970904T090000,19970905T090000," + "19970906T090000,19970907T090000,19970908T090000,19970909T090000," + "19970910T090000,19970911T090000");
-
- }
-
- @SmallTest
- public void testDailyUntilDec4() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;UNTIL=19971204", "19971128", 11, "19971128,19971129,19971130,19971201,19971202,19971203,19971204");
- }
-
- // Fails: infinite loop
- @SmallTest
- public void failingTestEveryOtherDayForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;INTERVAL=2", "19971128", 5, "19971128,19971130,19971202,19971204,19971206,...");
- }
-
- @SmallTest
- public void testEvery10Days5Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5", "19970902", 5, "19970902,19970912,19970922,19971002,19971012");
- }
-
- @SmallTest
- public void testWeeklyFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;COUNT=10", "19970902", 10, "19970902,19970909,19970916,19970923,19970930," + "19971007,19971014,19971021,19971028,19971104");
- }
-
- @SmallTest
- public void testWeeklyUntilDec24() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;UNTIL=19971224", "19970902", 25, "19970902,19970909,19970916,19970923,19970930," + "19971007,19971014,19971021,19971028,19971104," + "19971111,19971118,19971125,19971202,19971209," + "19971216,19971223");
- }
-
- @SmallTest
- public void testEveryOtherWeekForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU", "19970902", 11, "19970902,19970916,19970930,19971014,19971028," + "19971111,19971125,19971209,19971223,19980106," + "19980120,...");
- }
-
- @SmallTest
- public void testWeeklyOnTuesdayAndThursdayFor5Weeks() throws Exception {
- // if UNTIL date does not match start date, then until date treated as
- // occurring on midnight.
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;UNTIL=19971007;WKST=SU;BYDAY=TU,TH", "19970902T090000", 11, "19970902T090000,19970904T090000,19970909T090000,19970911T090000," + "19970916T090000,19970918T090000,19970923T090000,19970925T090000," + "19970930T090000,19971002T090000");
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH", "19970902T090000", 11, "19970902T090000,19970904T090000,19970909T090000,19970911T090000," + "19970916T090000,19970918T090000,19970923T090000,19970925T090000," + "19970930T090000,19971002T090000");
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH", "19970902", 11, "19970902,19970904,19970909,19970911,19970916," + "19970918,19970923,19970925,19970930,19971002");
- }
-
- @SmallTest
- public void testEveryOtherWeekOnMWFUntilDec24() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;\n" + " BYDAY=MO,WE,FR", "19970903T090000", 25, "19970903T090000,19970905T090000,19970915T090000,19970917T090000," + "19970919T090000,19970929T090000,19971001T090000,19971003T090000," + "19971013T090000,19971015T090000,19971017T090000,19971027T090000," + "19971029T090000,19971031T090000,19971110T090000,19971112T090000," + "19971114T090000,19971124T090000,19971126T090000,19971128T090000," + "19971208T090000,19971210T090000,19971212T090000,19971222T090000");
- }
-
- @SmallTest
- public void testEveryOtherWeekOnMWFUntilDec24a() throws Exception {
- // if the UNTIL date is timed, when the start is not, the time should be
- // ignored, so we get one more instance
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;\n" + " BYDAY=MO,WE,FR", "19970903", 25, "19970903,19970905,19970915,19970917," + "19970919,19970929,19971001,19971003," + "19971013,19971015,19971017,19971027," + "19971029,19971031,19971110,19971112," + "19971114,19971124,19971126,19971128," + "19971208,19971210,19971212,19971222," + "19971224");
- }
-
- // Fails with wrong times
- @SmallTest
- public void failingTestEveryOtherWeekOnMWFUntilDec24b() throws Exception {
- // test with an alternate timezone
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T090000Z;WKST=SU;\n" + " BYDAY=MO,WE,FR", "19970903T090000", 25, "19970903T160000,19970905T160000,19970915T160000,19970917T160000," + "19970919T160000,19970929T160000,19971001T160000,19971003T160000," + "19971013T160000,19971015T160000,19971017T160000,19971027T170000," + "19971029T170000,19971031T170000,19971110T170000,19971112T170000," + "19971114T170000,19971124T170000,19971126T170000,19971128T170000," + "19971208T170000,19971210T170000,19971212T170000,19971222T170000", null, PST);
- }
-
- @SmallTest
- public void testEveryOtherWeekOnTuThFor8Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH", "19970902", 8, "19970902,19970904,19970916,19970918,19970930," + "19971002,19971014,19971016");
- }
-
- @SmallTest
- public void testMonthlyOnThe1stFridayFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR", "19970905", 10, "19970905,19971003,19971107,19971205,19980102," + "19980206,19980306,19980403,19980501,19980605");
- }
-
- @SmallTest
- public void testMonthlyOnThe1stFridayUntilDec24() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR", "19970905", 4, "19970905,19971003,19971107,19971205");
- }
-
- @SmallTest
- public void testEveryOtherMonthOnThe1stAndLastSundayFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU", "19970907", 10, "19970907,19970928,19971102,19971130,19980104," + "19980125,19980301,19980329,19980503,19980531");
- }
-
- @SmallTest
- public void testMonthlyOnTheSecondToLastMondayOfTheMonthFor6Months() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO", "19970922", 6, "19970922,19971020,19971117,19971222,19980119," + "19980216");
- }
-
- @SmallTest
- public void testMonthlyOnTheThirdToLastDay() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYMONTHDAY=-3", "19970928", 6, "19970928,19971029,19971128,19971229,19980129,19980226,...");
- }
-
- @SmallTest
- public void testMonthlyOnThe2ndAnd15thFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15", "19970902", 10, "19970902,19970915,19971002,19971015,19971102," + "19971115,19971202,19971215,19980102,19980115");
- }
-
- @SmallTest
- public void testMonthlyOnTheFirstAndLastFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1", "19970930", 10, "19970930,19971001,19971031,19971101,19971130," + "19971201,19971231,19980101,19980131,19980201");
- }
-
- @SmallTest
- public void testEvery18MonthsOnThe10thThru15thFor10Occ() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,\n" + " 15", "19970910", 10, "19970910,19970911,19970912,19970913,19970914," + "19970915,19990310,19990311,19990312,19990313");
- }
-
- @SmallTest
- public void testEveryTuesdayEveryOtherMonth() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU", "19970902", 18, "19970902,19970909,19970916,19970923,19970930," + "19971104,19971111,19971118,19971125,19980106," + "19980113,19980120,19980127,19980303,19980310," + "19980317,19980324,19980331,...");
- }
-
- @SmallTest
- public void testYearlyInJuneAndJulyFor10Occurrences() throws Exception {
- // Note: Since none of the BYDAY, BYMONTHDAY or BYYEARDAY components
- // are specified, the day is gotten from DTSTART
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7", "19970610", 10, "19970610,19970710,19980610,19980710,19990610," + "19990710,20000610,20000710,20010610,20010710");
- }
-
- @SmallTest
- public void testEveryOtherYearOnJanuaryFebruaryAndMarchFor10Occurrences() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3", "19970310", 10, "19970310,19990110,19990210,19990310,20010110," + "20010210,20010310,20030110,20030210,20030310");
- }
-
- //Fails: wrong dates
- @SmallTest
- public void failingTestEvery3rdYearOnThe1st100thAnd200thDayFor10Occurrences() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200", "19970101", 10, "19970101,19970410,19970719,20000101,20000409," + "20000718,20030101,20030410,20030719,20060101");
- }
-
- // Fails: infinite loop
- @SmallTest
- public void failingTestEvery20thMondayOfTheYearForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=20MO", "19970519", 3, "19970519,19980518,19990517,...");
- }
-
- // Fails: generates wrong dates
- @SmallTest
- public void failingTestMondayOfWeekNumber20WhereTheDefaultStartOfTheWeekIsMonday() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO", "19970512", 3, "19970512,19980511,19990517,...");
- }
-
- @SmallTest
- public void testEveryThursdayInMarchForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH", "19970313", 11, "19970313,19970320,19970327,19980305,19980312," + "19980319,19980326,19990304,19990311,19990318," + "19990325,...");
- }
-
- //Fails: wrong dates
- @SmallTest
- public void failingTestEveryThursdayButOnlyDuringJuneJulyAndAugustForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8", "19970605", 39, "19970605,19970612,19970619,19970626,19970703," + "19970710,19970717,19970724,19970731,19970807," + "19970814,19970821,19970828,19980604,19980611," + "19980618,19980625,19980702,19980709,19980716," + "19980723,19980730,19980806,19980813,19980820," + "19980827,19990603,19990610,19990617,19990624," + "19990701,19990708,19990715,19990722,19990729," + "19990805,19990812,19990819,19990826,...");
- }
-
- //Fails: infinite loop
- @SmallTest
- public void failingTestEveryFridayThe13thForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13", "19970902", 5, "19980213,19980313,19981113,19990813,20001013," + "...");
- }
-
- @SmallTest
- public void testTheFirstSaturdayThatFollowsTheFirstSundayOfTheMonthForever() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13", "19970913", 10, "19970913,19971011,19971108,19971213,19980110," + "19980207,19980307,19980411,19980509,19980613," + "...");
- }
-
- @SmallTest
- public void testEvery4YearsThe1stTuesAfterAMonInNovForever() throws Exception {
- // US Presidential Election Day
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,\n" + " 5,6,7,8", "19961105", 3, "19961105,20001107,20041102,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestThe3rdInstanceIntoTheMonthOfOneOfTuesWedThursForNext3Months() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3", "19970904", 3, "19970904,19971007,19971106");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestThe2ndToLastWeekdayOfTheMonth() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2", "19970929", 7, "19970929,19971030,19971127,19971230,19980129," + "19980226,19980330,...");
- }
-
- // Fails: infinite loop
- @SmallTest
- public void failingTestEvery3HoursFrom900AmTo500PmOnASpecificDay() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970903T010000Z", "19970902", 7, "00000902,19970909,19970900,19970912,19970900," + "19970915,19970900");
- }
-
- // Fails: infinite loop
- @SmallTest
- public void failingTestEvery15MinutesFor6Occurrences() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MINUTELY;INTERVAL=15;COUNT=6", "19970902", 13, "00000902,19970909,19970900,19970909,19970915," + "19970909,19970930,19970909,19970945,19970910," + "19970900,19970910,19970915");
- }
-
- @SmallTest
- public void failingTestEveryHourAndAHalfFor4Occurrences() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MINUTELY;INTERVAL=90;COUNT=4", "19970902", 9, "00000902,19970909,19970900,19970910,19970930," + "19970912,19970900,19970913,19970930");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestAnExampleWhereTheDaysGeneratedMakesADifferenceBecauseOfWkst() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO", "19970805", 4, "19970805,19970810,19970819,19970824");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestAnExampleWhereTheDaysGeneratedMakesADifferenceBecauseOfWkst2() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU", "19970805", 8, "19970805,19970817,19970819,19970831");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestWithByDayAndByMonthDayFilter() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;COUNT=4;BYDAY=TU,SU;" + "BYMONTHDAY=13,14,15,16,17,18,19,20", "19970805", 8, "19970817,19970819,19970914,19970916");
- }
-
- // Failed: wrong dates
- @SmallTest
- public void failingTestAnnuallyInAugustOnTuesAndSunBetween13thAnd20th() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,SU;" + "BYMONTHDAY=13,14,15,16,17,18,19,20;BYMONTH=8", "19970605", 8, "19970817,19970819,19980816,19980818");
- }
-
- // Failed: wrong dates
- @SmallTest
- public void failingTestLastDayOfTheYearIsASundayOrTuesday() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,SU;BYYEARDAY=-1", "19940605", 8, "19951231,19961231,20001231,20021231");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestLastWeekdayOfMonth() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYSETPOS=-1;BYDAY=-1MO,-1TU,-1WE,-1TH,-1FR", "19940605", 8, "19940630,19940729,19940831,19940930," + "19941031,19941130,19941230,19950131,...");
- }
-
- // Fails: generates wrong dates
- @SmallTest
- public void failingTestMonthsThatStartOrEndOnFriday() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYMONTHDAY=1,-1;BYDAY=FR;COUNT=6", "19940605", 8, "19940701,19940930,19950331,19950630,19950901,19951201");
- }
-
- // Fails: can't go that far into future
- @SmallTest
- public void failingTestCenturiesThatAreNotLeapYears() throws Exception {
- // I can't think of a good reason anyone would want to specify both a
- // month day and a year day, so here's a really contrived example
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=100;BYYEARDAY=60;BYMONTHDAY=1", "19000101", 4, "19000301,21000301,22000301,23000301,...", null, "25000101", UTC);
- }
-
- // Fails: generates instances when it shouldn't
- @SmallTest
- public void failingTestNoInstancesGenerated() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=DAILY;UNTIL=19990101", "20000101", 4, "");
- }
-
- // Fails: generates instances when it shouldn't
- @SmallTest
- public void failingTestNoInstancesGenerated2() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=30", "20000101", 4, "");
- }
-
- // Fails: generates instances when it shouldn't
- @SmallTest
- public void failingTestNoInstancesGenerated3() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=4;BYYEARDAY=366", "20000101", 4, "");
- }
-
- //Fails: wrong dates
- @SmallTest
- public void failingTestLastWeekdayOfMarch() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYMONTH=3;BYDAY=SA,SU;BYSETPOS=-1", "20000101", 4, "20000326,20010331,20020331,20030330,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstWeekdayOfMarch() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYMONTH=3;BYDAY=SA,SU;BYSETPOS=1", "20000101", 4, "20000304,20010303,20020302,20030301,...");
- }
-
- // January 1999
- // Mo Tu We Th Fr Sa Su
- // 1 2 3 // < 4 days, so not a week
- // 4 5 6 7 8 9 10
-
- // January 2000
- // Mo Tu We Th Fr Sa Su
- // 1 2 // < 4 days, so not a week
- // 3 4 5 6 7 8 9
-
- // January 2001
- // Mo Tu We Th Fr Sa Su
- // 1 2 3 4 5 6 7
- // 8 9 10 11 12 13 14
-
- // January 2002
- // Mo Tu We Th Fr Sa Su
- // 1 2 3 4 5 6
- // 7 8 9 10 11 12 13
-
- /**
- * Find the first weekday of the first week of the year.
- * The first week of the year may be partial, and the first week is considered
- * to be the first one with at least four days.
- */
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstWeekdayOfFirstWeekOfYear() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYWEEKNO=1;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1", "19990101", 4, "19990104,20000103,20010101,20020101,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstSundayOfTheYear1() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYWEEKNO=1;BYDAY=SU", "19990101", 4, "19990110,20000109,20010107,20020106,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstSundayOfTheYear2() throws Exception {
- // TODO(msamuel): is this right?
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=1SU", "19990101", 4, "19990103,20000102,20010107,20020106,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstSundayOfTheYear3() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=SU;BYYEARDAY=1,2,3,4,5,6,7,8,9,10,11,12,13" + ";BYSETPOS=1", "19990101", 4, "19990103,20000102,20010107,20020106,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestFirstWeekdayOfYear() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1", "19990101", 4, "19990101,20000103,20010101,20020101,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestLastWeekdayOfFirstWeekOfYear() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYWEEKNO=1;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1", "19990101", 4, "19990108,20000107,20010105,20020104,...");
- }
-
- // January 1999
- // Mo Tu We Th Fr Sa Su
- // 1 2 3
- // 4 5 6 7 8 9 10
- // 11 12 13 14 15 16 17
- // 18 19 20 21 22 23 24
- // 25 26 27 28 29 30 31
-
- // Fails: wrong dates
- @SmallTest
- public void failingestSectesondWeekday1() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=2", "19990101", 4, "19990105,19990112,19990119,19990126,...");
- }
-
- // January 1997
- // Mo Tu We Th Fr Sa Su
- // 1 2 3 4 5
- // 6 7 8 9 10 11 12
- // 13 14 15 16 17 18 19
- // 20 21 22 23 24 25 26
- // 27 28 29 30 31
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestSecondWeekday2() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=2", "19970101", 4, "19970102,19970107,19970114,19970121,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestByYearDayAndByDayFilterInteraction() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYYEARDAY=15;BYDAY=3MO", "19990101", 4, "20010115,20070115,20180115,20240115,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestByDayWithNegWeekNoAsFilter() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;BYMONTHDAY=26;BYDAY=-1FR", "19990101", 4, "19990226,19990326,19991126,20000526,...");
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestLastWeekOfTheYear() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYWEEKNO=-1", "19990101", 6, "19991227,19991228,19991229,19991230,19991231,20001225,...");
- }
-
- // Fails: not enough dates generated
- @SmallTest
- public void failingTestUserSubmittedTest1() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=WE;BYDAY=SU,TU,TH,SA" + ";UNTIL=20000215T113000Z", "20000127T033000", 20, "20000127T033000,20000129T033000,20000130T033000,20000201T033000," + "20000210T033000,20000212T033000,20000213T033000,20000215T033000");
- }
-
- @SmallTest
- public void testAdvanceTo1() throws Exception {
- // a bunch of tests grabbed from above with an advance-to date tacked on
-
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH", "19970313", 11,
- /*"19970313,19970320,19970327,"*/"19980305,19980312," + "19980319,19980326,19990304,19990311,19990318," + "19990325,20000302,20000309,20000316,...", "19970601", UTC);
- }
-
- // Fails: infinite loop
- @SmallTest
- public void failingTestAdvanceTo2() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYDAY=20MO", "19970519", 3,
- /*"19970519,"*/"19980518,19990517,20000515,...", "19980515", UTC);
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestAdvanceTo3() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=3;UNTIL=20090101;BYYEARDAY=1,100,200", "19970101", 10,
- /*"19970101,19970410,19970719,20000101,"*/"20000409," + "20000718,20030101,20030410,20030719,20060101,20060410,20060719," + "20090101", "20000228", UTC);
- }
-
- //Fails: wrong dates
- @SmallTest
- public void failingTestAdvanceTo4() throws Exception {
- // make sure that count preserved
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200", "19970101", 10,
- /*"19970101,19970410,19970719,20000101,"*/"20000409," + "20000718,20030101,20030410,20030719,20060101", "20000228", UTC);
- }
-
- // Fails: too many dates
- @SmallTest
- public void FailingTestAdvanceTo5() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3", "19970310", 10,
- /*"19970310,"*/"19990110,19990210,19990310,20010110," + "20010210,20010310,20030110,20030210,20030310", "19980401", UTC);
- }
-
- @SmallTest
- public void testAdvanceTo6() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;UNTIL=19971224", "19970902", 25,
- /*"19970902,19970909,19970916,19970923,"*/"19970930," + "19971007,19971014,19971021,19971028,19971104," + "19971111,19971118,19971125,19971202,19971209," + "19971216,19971223", "19970930", UTC);
- }
-
- @SmallTest
- public void testAdvanceTo7() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;INTERVAL=18;BYMONTHDAY=10,11,12,13,14,\n" + " 15", "19970910", 5,
- /*"19970910,19970911,19970912,19970913,19970914," +
- "19970915,"*/"19990310,19990311,19990312,19990313,19990314,...", "19990101", UTC);
- }
-
- @SmallTest
- public void testAdvanceTo8() throws Exception {
- // advancing into the past
- runRecurrenceIteratorTest("RRULE:FREQ=MONTHLY;INTERVAL=18;BYMONTHDAY=10,11,12,13,14,\n" + " 15", "19970910", 11, "19970910,19970911,19970912,19970913,19970914," + "19970915,19990310,19990311,19990312,19990313,19990314,...", "19970901", UTC);
- }
-
- // Fails: wrong dates
- @SmallTest
- public void failingTestAdvanceTo9() throws Exception {
- // skips first instance
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=100;BYMONTH=2;BYMONTHDAY=29", "19000101", 5,
- // would return 2000
- "24000229,28000229,32000229,36000229,40000229,...", "20040101", UTC);
- }
-
- @SmallTest
- public void testAdvanceTo10() throws Exception {
- // filter hits until date before first instnace
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;INTERVAL=100;BYMONTH=2;BYMONTHDAY=29;UNTIL=21000101", "19000101", 5, "", "20040101", UTC);
- }
-
- // Fails: generates wrong dates
- @SmallTest
- public void failingTestAdvanceTo11() throws Exception {
- // advancing something that returns no instances
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=30", "20000101", 10, "", "19970901", UTC);
- }
-
- // Fails: generates wrong dates
- @SmallTest
- public void failingTestAdvanceTo12() throws Exception {
- // advancing something that returns no instances and has a BYSETPOS rule
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=30,31;BYSETPOS=1", "20000101", 10, "", "19970901", UTC);
- }
-
- // Fails: generates wrong dates
- @SmallTest
- public void failingTestAdvanceTo13() throws Exception {
- // advancing way past year generator timeout
- runRecurrenceIteratorTest("RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=28", "20000101", 10, "", "25000101", UTC);
- }
-
- /**
- * a testcase that yielded dupes due to bysetPos evilness
- */
- @SmallTest
- public void infiniteTestCaseThatYieldedDupes() throws Exception {
- runRecurrenceIteratorTest("RRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=1;BYMONTH=9,1,12,8" + ";BYMONTHDAY=-9,-29,24;BYSETPOS=-1,-4,10,-6,-1,-10,-10,-9,-8", "20060528", 200, "20060924,20061203,20061224,20070902,20071223,20080803,20080824," + "20090823,20100103,20100124,20110123,20120902,20121223,20130922," + "20140803,20140824,20150823,20160103,20160124,20170924,20171203," + "20171224,20180902,20181223,20190922,20200823,20210103,20210124," + "20220123,20230924,20231203,20231224,20240922,20250803,20250824," + "20260823,20270103,20270124,20280123,20280924,20281203,20281224," + "20290902,20291223,20300922,20310803,20310824,20330123,20340924," + "20341203,20341224,20350902,20351223,20360803,20360824,20370823," + "20380103,20380124,20390123,20400902,20401223,20410922,20420803," + "20420824,20430823,20440103,20440124,20450924,20451203,20451224," + "20460902,20461223,20470922,20480823,20490103,20490124,20500123," + "20510924,20511203,20511224,20520922,20530803,20530824,20540823," + "20550103,20550124,20560123,20560924,20561203,20561224,20570902," + "20571223,20580922,20590803,20590824,20610123,20620924,20621203," + "20621224,20630902,20631223,20640803,20640824,20650823,20660103," + "20660124,20670123,20680902,20681223,20690922,20700803,20700824," + "20710823,20720103,20720124,20730924,20731203,20731224,20740902," + "20741223,20750922,20760823,20770103,20770124,20780123,20790924," + "20791203,20791224,20800922,20810803,20810824,20820823,20830103," + "20830124,20840123,20840924,20841203,20841224,20850902,20851223," + "20860922,20870803,20870824,20890123,20900924,20901203,20901224," + "20910902,20911223,20920803,20920824,20930823,20940103,20940124," + "20950123,20960902,20961223,20970922,20980803,20980824,20990823," + "21000103,21000124,21010123,21020924,21021203,21021224,21030902," + "21031223,21040803,21040824,21050823,21060103,21060124,21070123," + "21080902,21081223,21090922,21100803,21100824,21110823,21120103," + "21120124,21130924,21131203,21131224,21140902,21141223,21150922," + "21160823,21170103,21170124,21180123,21190924,21191203,21191224," + "21200922,21210803,21210824,21220823,...");
- }
-}