Utils.java revision a27a886892fe3ec5edbc63c0b58e0a988623011a
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/*
2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License.
6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at
7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and
14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License.
15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */
16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
17146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpackage com.android.calendar;
18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
19a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErikimport static android.provider.CalendarContract.EXTRA_EVENT_BEGIN_TIME;
20e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
21d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport com.android.calendar.CalendarController.ViewType;
22d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
23d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.app.Activity;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Intent;
26e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chanimport android.content.SharedPreferences;
275b2a907fa3a983f74bb48da86846e351c2a464d0Isaac Katzenelsonimport android.content.res.Configuration;
28ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport android.database.Cursor;
29a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErikimport android.database.MatrixCursor;
301ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.net.Uri;
31d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chanimport android.os.Bundle;
32eb10fa8bee049e0052b5cb53dcfbdaccef9f2740Erikimport android.text.TextUtils;
3329190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawaimport android.text.format.DateUtils;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
351ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport android.util.Log;
36636269c7220a2b12e090cab43a91eb34922eb61fAndy McFaddenimport com.android.calendar.CalendarUtils.TimeZoneUtils;
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
3882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.ArrayList;
3956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashiimport java.util.Calendar;
401427657d0bf7e69b831aa495828f67b45b69fd99Erikimport java.util.Formatter;
4182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelsonimport java.util.Iterator;
421ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erikimport java.util.List;
43ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chanimport java.util.Map;
4456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class Utils {
463dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final boolean DEBUG = true;
473dc5e908a825b879978ba523d9099dc2255da9a5Erik    private static final String TAG = "CalUtils";
48bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    // Set to 0 until we have UI to perform undo
49bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    public static final long UNDO_DELAY = 0;
50bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan
5179f228124de7d98146ca526d743436f6419e2365Erik    // For recurring events which instances of the series are being modified
5279f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_UNINITIALIZED = 0;
5379f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_SELECTED = 1;
5479f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL_FOLLOWING = 2;
5579f228124de7d98146ca526d743436f6419e2365Erik    public static final int MODIFY_ALL = 3;
5679f228124de7d98146ca526d743436f6419e2365Erik
577b92da258a480284dcc15a518ea570072329a31dErik    // When the edit event view finishes it passes back the appropriate exit
587b92da258a480284dcc15a518ea570072329a31dErik    // code.
597b92da258a480284dcc15a518ea570072329a31dErik    public static final int DONE_REVERT = 1 << 0;
607b92da258a480284dcc15a518ea570072329a31dErik    public static final int DONE_SAVE = 1 << 1;
617b92da258a480284dcc15a518ea570072329a31dErik    public static final int DONE_DELETE = 1 << 2;
627b92da258a480284dcc15a518ea570072329a31dErik    // And should re run with DONE_EXIT if it should also leave the view, just
637b92da258a480284dcc15a518ea570072329a31dErik    // exiting is identical to reverting
647b92da258a480284dcc15a518ea570072329a31dErik    public static final int DONE_EXIT = 1 << 0;
6579f228124de7d98146ca526d743436f6419e2365Erik
66ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String OPEN_EMAIL_MARKER = " <";
67ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    protected static final String CLOSE_EMAIL_MARKER = ">";
68ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
69d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW";
70d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_KEY_VIEW_TYPE = "VIEW";
71d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY";
72275232dae58bb24e3360a779ada9d24601a99bcfErik
73981874e61ecf29a96a77601a3172b2503b6537eeErik    public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3;
74981874e61ecf29a96a77601a3172b2503b6537eeErik
75a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    // The name of the shared preferences file. This name must be maintained for
76a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    // historical
77a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    // reasons, as it's what PreferenceManager assigned the first time the file
78a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    // was created.
79a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    private static final String SHARED_PREFS_NAME = "com.android.calendar_preferences";
8035d1362a75eac7cebbe9de23d08fea08c4aac817Erik
81a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    private static final TimeZoneUtils mTZUtils = new TimeZoneUtils(SHARED_PREFS_NAME);
82b60218a31d948ea0a549daf6464063d20b48421fMichael Chan    private static boolean mAllowWeekForDetailView = false;
83ca4786769151f97069980443ce43d9c4f867ac5bErik    private static long mTardis = 0;
84d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
85d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getViewTypeFromIntentAndSharedPref(Activity activity) {
86dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        Intent intent = activity.getIntent();
87dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        Bundle extras = intent.getExtras();
884b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(activity);
89d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
907b92da258a480284dcc15a518ea570072329a31dErik        if (TextUtils.equals(intent.getAction(), Intent.ACTION_EDIT)) {
91dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            return ViewType.EDIT;
92dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        }
93d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        if (extras != null) {
94d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            if (extras.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) {
95d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // This is the "detail" view which is either agenda or day view
964b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa                return prefs.getInt(GeneralPreferences.KEY_DETAILED_VIEW,
974b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa                        GeneralPreferences.DEFAULT_DETAILED_VIEW);
98d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras.getString(INTENT_KEY_VIEW_TYPE))) {
99d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                // Not sure who uses this. This logic came from LaunchActivity
100d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan                return ViewType.DAY;
101d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan            }
102d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        }
103d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
104d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        // Default to the last view
1057b92da258a480284dcc15a518ea570072329a31dErik        return prefs.getInt(
1067b92da258a480284dcc15a518ea570072329a31dErik                GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW);
107d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
108ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
109235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    /**
110064beb957ae443760118023a40fd7001eb11c1a1RoboErik     * Gets the intent action for telling the widget to update.
111064beb957ae443760118023a40fd7001eb11c1a1RoboErik     */
112064beb957ae443760118023a40fd7001eb11c1a1RoboErik    public static String getWidgetUpdateAction(Context context) {
113064beb957ae443760118023a40fd7001eb11c1a1RoboErik        return context.getPackageName() + ".APPWIDGET_UPDATE";
114064beb957ae443760118023a40fd7001eb11c1a1RoboErik    }
115064beb957ae443760118023a40fd7001eb11c1a1RoboErik
116064beb957ae443760118023a40fd7001eb11c1a1RoboErik    /**
117064beb957ae443760118023a40fd7001eb11c1a1RoboErik     * Gets the intent action for telling the widget to update.
118064beb957ae443760118023a40fd7001eb11c1a1RoboErik     */
119064beb957ae443760118023a40fd7001eb11c1a1RoboErik    public static String getWidgetScheduledUpdateAction(Context context) {
120064beb957ae443760118023a40fd7001eb11c1a1RoboErik        return context.getPackageName() + ".APPWIDGET_SCHEDULED_UPDATE";
121064beb957ae443760118023a40fd7001eb11c1a1RoboErik    }
122064beb957ae443760118023a40fd7001eb11c1a1RoboErik
123064beb957ae443760118023a40fd7001eb11c1a1RoboErik    /**
124064beb957ae443760118023a40fd7001eb11c1a1RoboErik     * Gets the intent action for telling the widget to update.
125064beb957ae443760118023a40fd7001eb11c1a1RoboErik     */
126064beb957ae443760118023a40fd7001eb11c1a1RoboErik    public static String getSearchAuthority(Context context) {
127064beb957ae443760118023a40fd7001eb11c1a1RoboErik        return context.getPackageName() + ".CalendarRecentSuggestionsProvider";
128064beb957ae443760118023a40fd7001eb11c1a1RoboErik    }
129064beb957ae443760118023a40fd7001eb11c1a1RoboErik
130064beb957ae443760118023a40fd7001eb11c1a1RoboErik    /**
1317b92da258a480284dcc15a518ea570072329a31dErik     * Writes a new home time zone to the db. Updates the home time zone in the
1327b92da258a480284dcc15a518ea570072329a31dErik     * db asynchronously and updates the local cache. Sending a time zone of
1337b92da258a480284dcc15a518ea570072329a31dErik     * **tbd** will cause it to be set to the device's time zone. null or empty
1347b92da258a480284dcc15a518ea570072329a31dErik     * tz will be ignored.
1353dc5e908a825b879978ba523d9099dc2255da9a5Erik     *
1363dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param context The calling activity
1373dc5e908a825b879978ba523d9099dc2255da9a5Erik     * @param timeZone The time zone to set Calendar to, or **tbd**
1383dc5e908a825b879978ba523d9099dc2255da9a5Erik     */
1393dc5e908a825b879978ba523d9099dc2255da9a5Erik    public static void setTimeZone(Context context, String timeZone) {
140a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik        mTZUtils.setTimeZone(context, timeZone);
1413dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
1423dc5e908a825b879978ba523d9099dc2255da9a5Erik
1433dc5e908a825b879978ba523d9099dc2255da9a5Erik    /**
1447b92da258a480284dcc15a518ea570072329a31dErik     * Gets the time zone that Calendar should be displayed in This is a helper
1457b92da258a480284dcc15a518ea570072329a31dErik     * method to get the appropriate time zone for Calendar. If this is the
1467b92da258a480284dcc15a518ea570072329a31dErik     * first time this method has been called it will initiate an asynchronous
1477b92da258a480284dcc15a518ea570072329a31dErik     * query to verify that the data in preferences is correct. The callback
1487b92da258a480284dcc15a518ea570072329a31dErik     * supplied will only be called if this query returns a value other than
1497b92da258a480284dcc15a518ea570072329a31dErik     * what is stored in preferences and should cause the calling activity to
1507b92da258a480284dcc15a518ea570072329a31dErik     * refresh anything that depends on calling this method.
151235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     *
152235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     * @param context The calling activity
1537b92da258a480284dcc15a518ea570072329a31dErik     * @param callback The runnable that should execute if a query returns new
1547b92da258a480284dcc15a518ea570072329a31dErik     *            values
1557b92da258a480284dcc15a518ea570072329a31dErik     * @return The string value representing the time zone Calendar should
1567b92da258a480284dcc15a518ea570072329a31dErik     *         display
157235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik     */
158235d59cf61769ec8ab777d81cd1ceb2e7530f439Erik    public static String getTimeZone(Context context, Runnable callback) {
159a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik        return mTZUtils.getTimeZone(context, callback);
16045efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
16145efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
1621427657d0bf7e69b831aa495828f67b45b69fd99Erik    /**
1631427657d0bf7e69b831aa495828f67b45b69fd99Erik     * Formats a date or a time range according to the local conventions.
1641427657d0bf7e69b831aa495828f67b45b69fd99Erik     *
1651427657d0bf7e69b831aa495828f67b45b69fd99Erik     * @param context the context is required only if the time is shown
1661427657d0bf7e69b831aa495828f67b45b69fd99Erik     * @param startMillis the start time in UTC milliseconds
1671427657d0bf7e69b831aa495828f67b45b69fd99Erik     * @param endMillis the end time in UTC milliseconds
16829190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa     * @param flags a bit mask of options See {@link DateUtils#formatDateRange(Context, Formatter,
16929190975b9238dd6841f822f82f2fb83b0557f36Daisuke Miyakawa     * long, long, int, String) formatDateRange}
1701427657d0bf7e69b831aa495828f67b45b69fd99Erik     * @return a string containing the formatted date/time range.
1711427657d0bf7e69b831aa495828f67b45b69fd99Erik     */
1727b92da258a480284dcc15a518ea570072329a31dErik    public static String formatDateRange(
1737b92da258a480284dcc15a518ea570072329a31dErik            Context context, long startMillis, long endMillis, int flags) {
174a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik        return mTZUtils.formatDateRange(context, startMillis, endMillis, flags);
175a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    }
176a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik
177a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik    public static String getSharedPreference(Context context, String key, String defaultValue) {
178a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
179a48b9d426236d8d26bd99602bf0a84315b3f1b09Erik        return prefs.getString(key, defaultValue);
1801427657d0bf7e69b831aa495828f67b45b69fd99Erik    }
1811427657d0bf7e69b831aa495828f67b45b69fd99Erik
182d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    public static int getSharedPreference(Context context, String key, int defaultValue) {
1834b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
184d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan        return prefs.getInt(key, defaultValue);
185d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    }
186d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan
187ca4786769151f97069980443ce43d9c4f867ac5bErik    public static boolean getSharedPreference(Context context, String key, boolean defaultValue) {
188ca4786769151f97069980443ce43d9c4f867ac5bErik        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
189ca4786769151f97069980443ce43d9c4f867ac5bErik        return prefs.getBoolean(key, defaultValue);
190ca4786769151f97069980443ce43d9c4f867ac5bErik    }
191ca4786769151f97069980443ce43d9c4f867ac5bErik
192f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang    /**
193f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * Asynchronously sets the preference with the given key to the given value
194f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     *
195f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param context the context to use to get preferences from
196f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param key the key of the preference to set
197f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     * @param value the value to set
198f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang     */
199fbce65e53c7a111955f638db5bf8bee35381e5b7Erik    public static void setSharedPreference(Context context, String key, String value) {
2004b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
20124fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick        prefs.edit().putString(key, value).apply();
20245efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan    }
20345efa09d6e06f5569b2c0ae0dae0436dbfe6cb28Michael Chan
204ca4786769151f97069980443ce43d9c4f867ac5bErik    protected static void tardis() {
205ca4786769151f97069980443ce43d9c4f867ac5bErik        mTardis = System.currentTimeMillis();
206ca4786769151f97069980443ce43d9c4f867ac5bErik    }
207ca4786769151f97069980443ce43d9c4f867ac5bErik
208ca4786769151f97069980443ce43d9c4f867ac5bErik    protected static long getTardis() {
209ca4786769151f97069980443ce43d9c4f867ac5bErik        return mTardis;
210ca4786769151f97069980443ce43d9c4f867ac5bErik    }
211ca4786769151f97069980443ce43d9c4f867ac5bErik
2123dc5e908a825b879978ba523d9099dc2255da9a5Erik    static void setSharedPreference(Context context, String key, boolean value) {
2134b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
2143dc5e908a825b879978ba523d9099dc2255da9a5Erik        SharedPreferences.Editor editor = prefs.edit();
2153dc5e908a825b879978ba523d9099dc2255da9a5Erik        editor.putBoolean(key, value);
216275232dae58bb24e3360a779ada9d24601a99bcfErik        editor.apply();
2173dc5e908a825b879978ba523d9099dc2255da9a5Erik    }
2183dc5e908a825b879978ba523d9099dc2255da9a5Erik
219d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan    static void setSharedPreference(Context context, String key, int value) {
220d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
221d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan        SharedPreferences.Editor editor = prefs.edit();
222d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan        editor.putInt(key, value);
223d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan        editor.apply();
224d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan    }
225d885c1a5876735bbf2c0086956101bd70bac37e7Michael Chan
226d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan    /**
227d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * Save default agenda/day/week/month view for next time
228d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     *
229d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param context
230d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     * @param viewId {@link CalendarController.ViewType}
231d6734dbbd704cdb1bc331d1bd74b7a3be58f69ffMichael Chan     */
232e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    static void setDefaultView(Context context, int viewId) {
2334b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
234e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        SharedPreferences.Editor editor = prefs.edit();
235f4ad4757de32ace6971cf4c3db7c395aa249001aMason Tang
236b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        boolean validDetailView = false;
237b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        if (mAllowWeekForDetailView && viewId == CalendarController.ViewType.WEEK) {
238b60218a31d948ea0a549daf6464063d20b48421fMichael Chan            validDetailView = true;
239b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        } else {
240b60218a31d948ea0a549daf6464063d20b48421fMichael Chan            validDetailView = viewId == CalendarController.ViewType.AGENDA
241b60218a31d948ea0a549daf6464063d20b48421fMichael Chan                    || viewId == CalendarController.ViewType.DAY;
242b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        }
243b60218a31d948ea0a549daf6464063d20b48421fMichael Chan
244b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        if (validDetailView) {
245b60218a31d948ea0a549daf6464063d20b48421fMichael Chan            // Record the detail start view
2464b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa            editor.putInt(GeneralPreferences.KEY_DETAILED_VIEW, viewId);
247e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        }
248e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
249e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan        // Record the (new) start view
2504b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        editor.putInt(GeneralPreferences.KEY_START_VIEW, viewId);
25124fac46d6b87ce21d5e6a4b1c0fdcaa83d408997Brad Fitzpatrick        editor.apply();
252e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan    }
253e8aa59d4575d712601a133a9263acc23adbc8c17Michael Chan
254a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
255a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames());
256a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = cursor.getColumnCount();
257a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        String data[] = new String[numColumns];
258a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        cursor.moveToPosition(-1);
259a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        while (cursor.moveToNext()) {
260a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            for (int i = 0; i < numColumns; i++) {
261a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                data[i] = cursor.getString(i);
262a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
263a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            newCursor.addRow(data);
264a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
265a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return newCursor;
266a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
267a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
268a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    /**
269a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     * Compares two cursors to see if they contain the same data.
270a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     *
2717b92da258a480284dcc15a518ea570072329a31dErik     * @return Returns true of the cursors contain the same data and are not
2727b92da258a480284dcc15a518ea570072329a31dErik     *         null, false otherwise
273a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik     */
274a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    public static boolean compareCursors(Cursor c1, Cursor c2) {
2757b92da258a480284dcc15a518ea570072329a31dErik        if (c1 == null || c2 == null) {
276a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
277a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
278a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
279a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        int numColumns = c1.getColumnCount();
280a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (numColumns != c2.getColumnCount()) {
281a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
282a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
283a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
284a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        if (c1.getCount() != c2.getCount()) {
285a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            return false;
286a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
287a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
288a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c1.moveToPosition(-1);
289a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        c2.moveToPosition(-1);
2907b92da258a480284dcc15a518ea570072329a31dErik        while (c1.moveToNext() && c2.moveToNext()) {
2917b92da258a480284dcc15a518ea570072329a31dErik            for (int i = 0; i < numColumns; i++) {
2927b92da258a480284dcc15a518ea570072329a31dErik                if (!TextUtils.equals(c1.getString(i), c2.getString(i))) {
293a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                    return false;
294a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik                }
295a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik            }
296a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        }
297a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
298a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik        return true;
299a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik    }
300a144f86b41170e8ee7fe8d966cc51c5fc90cd44aErik
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * If the given intent specifies a time (in milliseconds since the epoch),
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * then that time is returned. Otherwise, the current time is returned.
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final long timeFromIntentInMillis(Intent intent) {
3067b92da258a480284dcc15a518ea570072329a31dErik        // If the time was specified, then use that. Otherwise, use the current
3077b92da258a480284dcc15a518ea570072329a31dErik        // time.
3081ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        Uri data = intent.getData();
309a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik        long millis = intent.getLongExtra(EXTRA_EVENT_BEGIN_TIME, -1);
3101ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        if (millis == -1 && data != null && data.isHierarchical()) {
3111ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            List<String> path = data.getPathSegments();
3127b92da258a480284dcc15a518ea570072329a31dErik            if (path.size() == 2 && path.get(0).equals("time")) {
3131ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                try {
3141ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                    millis = Long.valueOf(data.getLastPathSegment());
3151ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                } catch (NumberFormatException e) {
3167b92da258a480284dcc15a518ea570072329a31dErik                    Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time "
3177b92da258a480284dcc15a518ea570072329a31dErik                            + "found. Using current time.");
3181ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik                }
3191ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik            }
3201ef7f3ae2831dce8fa5e350f78ac4258c1a0a605Erik        }
32176727b7a9cf780f200414548b9d454bf9a701e3eErik        if (millis <= 0) {
322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            millis = System.currentTimeMillis();
323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return millis;
325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
3287b92da258a480284dcc15a518ea570072329a31dErik     * Formats the given Time object so that it gives the month and year (for
3297b92da258a480284dcc15a518ea570072329a31dErik     * example, "September 2007").
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the time to format
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the string containing the weekday and the date
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
334ad36a3c3cde7a2ec6d3a35d2529d46f03bd8d59dMichael Chan    public static String formatMonthYear(Context context, Time time) {
335cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
336cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik                | DateUtils.FORMAT_SHOW_YEAR;
337cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik        long millis = time.toMillis(true);
338cfa204ba5c59eb6ebd4b54788ceb31010e4a37a0RoboErik        return formatDateRange(context, millis, millis, flags);
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
3424c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * Returns a list joined together by the provided delimiter, for example,
3434c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * ["a", "b", "c"] could be joined into "a,b,c"
3444c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     *
3454c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param things the things to join together
3464c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @param delim the delimiter to use
3474c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     * @return a string contained the things joined together
3484c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang     */
3494c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    public static String join(List<?> things, String delim) {
3504c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        StringBuilder builder = new StringBuilder();
3514c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        boolean first = true;
3524c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        for (Object thing : things) {
3534c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            if (first) {
3544c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                first = false;
3554c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            } else {
3564c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang                builder.append(delim);
3574c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            }
3584c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang            builder.append(thing.toString());
3594c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        }
3604c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang        return builder.toString();
3614c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    }
3624c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang
3634c8871bf5dee3b3586b375aee98effde31b781a8Mason Tang    /**
364981874e61ecf29a96a77601a3172b2503b6537eeErik     * Returns the week since {@link Time#EPOCH_JULIAN_DAY} (Jan 1, 1970)
365981874e61ecf29a96a77601a3172b2503b6537eeErik     * adjusted for first day of week.
366981874e61ecf29a96a77601a3172b2503b6537eeErik     *
367981874e61ecf29a96a77601a3172b2503b6537eeErik     * This takes a julian day and the week start day and calculates which
368981874e61ecf29a96a77601a3172b2503b6537eeErik     * week since {@link Time#EPOCH_JULIAN_DAY} that day occurs in, starting
369981874e61ecf29a96a77601a3172b2503b6537eeErik     * at 0. *Do not* use this to compute the ISO week number for the year.
370981874e61ecf29a96a77601a3172b2503b6537eeErik     *
371981874e61ecf29a96a77601a3172b2503b6537eeErik     * @param julianDay The julian day to calculate the week number for
372981874e61ecf29a96a77601a3172b2503b6537eeErik     * @param firstDayOfWeek Which week day is the first day of the week,
373981874e61ecf29a96a77601a3172b2503b6537eeErik     *          see {@link Time#SUNDAY}
374981874e61ecf29a96a77601a3172b2503b6537eeErik     * @return Weeks since the epoch
375981874e61ecf29a96a77601a3172b2503b6537eeErik     */
376981874e61ecf29a96a77601a3172b2503b6537eeErik    public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) {
377981874e61ecf29a96a77601a3172b2503b6537eeErik        int diff = Time.THURSDAY - firstDayOfWeek;
378981874e61ecf29a96a77601a3172b2503b6537eeErik        if (diff < 0) {
379981874e61ecf29a96a77601a3172b2503b6537eeErik            diff += 7;
380981874e61ecf29a96a77601a3172b2503b6537eeErik        }
381981874e61ecf29a96a77601a3172b2503b6537eeErik        int refDay = Time.EPOCH_JULIAN_DAY - diff;
382981874e61ecf29a96a77601a3172b2503b6537eeErik        return (julianDay - refDay) / 7;
383981874e61ecf29a96a77601a3172b2503b6537eeErik    }
384981874e61ecf29a96a77601a3172b2503b6537eeErik
385981874e61ecf29a96a77601a3172b2503b6537eeErik    /**
386981874e61ecf29a96a77601a3172b2503b6537eeErik     * Takes a number of weeks since the epoch and calculates the Julian day of
387981874e61ecf29a96a77601a3172b2503b6537eeErik     * the Monday for that week.
388981874e61ecf29a96a77601a3172b2503b6537eeErik     *
389981874e61ecf29a96a77601a3172b2503b6537eeErik     * This assumes that the week containing the {@link Time#EPOCH_JULIAN_DAY}
390981874e61ecf29a96a77601a3172b2503b6537eeErik     * is considered week 0. It returns the Julian day for the Monday
391981874e61ecf29a96a77601a3172b2503b6537eeErik     * {@code week} weeks after the Monday of the week containing the epoch.
392981874e61ecf29a96a77601a3172b2503b6537eeErik     *
393981874e61ecf29a96a77601a3172b2503b6537eeErik     * @param week Number of weeks since the epoch
394981874e61ecf29a96a77601a3172b2503b6537eeErik     * @return The julian day for the Monday of the given week since the epoch
395981874e61ecf29a96a77601a3172b2503b6537eeErik     */
396981874e61ecf29a96a77601a3172b2503b6537eeErik    public static int getJulianMondayFromWeeksSinceEpoch(int week) {
397981874e61ecf29a96a77601a3172b2503b6537eeErik        return MONDAY_BEFORE_JULIAN_EPOCH + week * 7;
398981874e61ecf29a96a77601a3172b2503b6537eeErik    }
399981874e61ecf29a96a77601a3172b2503b6537eeErik
400981874e61ecf29a96a77601a3172b2503b6537eeErik    /**
40156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Get first day of week as android.text.format.Time constant.
4027b92da258a480284dcc15a518ea570072329a31dErik     *
40356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return the first day of week in android.text.format.Time
40456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
4058e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang    public static int getFirstDayOfWeek(Context context) {
4064b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
4077b92da258a480284dcc15a518ea570072329a31dErik        String pref = prefs.getString(
4087b92da258a480284dcc15a518ea570072329a31dErik                GeneralPreferences.KEY_WEEK_START_DAY, GeneralPreferences.WEEK_START_DEFAULT);
4098e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
4108e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        int startDay;
4114b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        if (GeneralPreferences.WEEK_START_DEFAULT.equals(pref)) {
4128e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Calendar.getInstance().getFirstDayOfWeek();
4138e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        } else {
4148e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang            startDay = Integer.parseInt(pref);
4158e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang        }
4168e3d430a020744faa21bf4ca24f1a99c36ec5c4fMason Tang
41756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        if (startDay == Calendar.SATURDAY) {
41856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SATURDAY;
41956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else if (startDay == Calendar.MONDAY) {
42056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.MONDAY;
42156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        } else {
42256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi            return Time.SUNDAY;
42356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        }
42456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
42556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
42656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
427d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa     * @return true when week number should be shown.
428981874e61ecf29a96a77601a3172b2503b6537eeErik     */
429981874e61ecf29a96a77601a3172b2503b6537eeErik    public static boolean getShowWeekNumber(Context context) {
430d644b0df14ae6e204369b3454d16976fba32f15cDaisuke Miyakawa        final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
431981874e61ecf29a96a77601a3172b2503b6537eeErik        return prefs.getBoolean(
432981874e61ecf29a96a77601a3172b2503b6537eeErik                GeneralPreferences.KEY_SHOW_WEEK_NUM, GeneralPreferences.DEFAULT_SHOW_WEEK_NUM);
433981874e61ecf29a96a77601a3172b2503b6537eeErik    }
434981874e61ecf29a96a77601a3172b2503b6537eeErik
435981874e61ecf29a96a77601a3172b2503b6537eeErik    /**
43640bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * @return true when declined events should be hidden.
43740bcd101b212c9863c3110c05a487a7ae6ebc3caErik     */
43840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    public static boolean getHideDeclinedEvents(Context context) {
43940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
44040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        return prefs.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED, false);
44140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
44240bcd101b212c9863c3110c05a487a7ae6ebc3caErik
44391b01ed605e36fc5a7a924c226597a62c789b50dErik    public static int getDaysPerWeek(Context context) {
44491b01ed605e36fc5a7a924c226597a62c789b50dErik        final SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
44591b01ed605e36fc5a7a924c226597a62c789b50dErik        return prefs.getInt(GeneralPreferences.KEY_DAYS_PER_WEEK, 7);
44691b01ed605e36fc5a7a924c226597a62c789b50dErik    }
44791b01ed605e36fc5a7a924c226597a62c789b50dErik
44840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    /**
44956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Saturday or not.
4507b92da258a480284dcc15a518ea570072329a31dErik     *
45156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
45256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
45356adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Saturday position
45456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
45556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSaturday(int column, int firstDayOfWeek) {
45656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 6)
4577b92da258a480284dcc15a518ea570072329a31dErik                || (firstDayOfWeek == Time.MONDAY && column == 5)
4587b92da258a480284dcc15a518ea570072329a31dErik                || (firstDayOfWeek == Time.SATURDAY && column == 0);
45956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
46056adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi
46156adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    /**
46256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * Determine whether the column position is Sunday or not.
4637b92da258a480284dcc15a518ea570072329a31dErik     *
46456adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param column the column position
46556adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @param firstDayOfWeek the first day of week in android.text.format.Time
46656adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     * @return true if the column is Sunday position
46756adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi     */
46856adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    public static boolean isSunday(int column, int firstDayOfWeek) {
46956adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi        return (firstDayOfWeek == Time.SUNDAY && column == 0)
4707b92da258a480284dcc15a518ea570072329a31dErik                || (firstDayOfWeek == Time.MONDAY && column == 6)
4717b92da258a480284dcc15a518ea570072329a31dErik                || (firstDayOfWeek == Time.SATURDAY && column == 1);
47256adc7b3f9e62ada7f3708c5c7228e8ac5af1755Takaoka G. Tadashi    }
473ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan
474ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    /**
4759da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik     * Convert given UTC time into current local time. This assumes it is for an
4769da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik     * allday event and will adjust the time to be on a midnight boundary.
4773ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     *
4783ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param recycle Time object to recycle, otherwise null.
4793ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     * @param utcTime Time to convert, in UTC.
4809da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik     * @param tz The time zone to convert this time to.
4813ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang     */
4829da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik    public static long convertAlldayUtcToLocal(Time recycle, long utcTime, String tz) {
4833ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        if (recycle == null) {
4843ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang            recycle = new Time();
4853ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        }
4863ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.timezone = Time.TIMEZONE_UTC;
4873ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        recycle.set(utcTime);
4889da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        recycle.timezone = tz;
4899da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        return recycle.normalize(true);
4909da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik    }
4919da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik
4929da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik    public static long convertAlldayLocalToUTC(Time recycle, long localTime, String tz) {
4939da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        if (recycle == null) {
4949da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik            recycle = new Time();
4959da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        }
4969da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        recycle.timezone = tz;
4979da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        recycle.set(localTime);
4989da910f65de0a325d4268d88f0cf2e2fd653f24aRoboErik        recycle.timezone = Time.TIMEZONE_UTC;
4993ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang        return recycle.normalize(true);
5003ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    }
5013ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang
5023ea333d41c04fd5f3a5d45f540c17894874429e8Mason Tang    /**
503ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * Scan through a cursor of calendars and check if names are duplicated.
5047b92da258a480284dcc15a518ea570072329a31dErik     * This travels a cursor containing calendar display names and fills in the
5057b92da258a480284dcc15a518ea570072329a31dErik     * provided map with whether or not each name is repeated.
506ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     *
507ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param isDuplicateName The map to put the duplicate check results in.
508ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param cursor The query of calendars to check
509ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     * @param nameIndex The column of the query that contains the display name
510ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan     */
5117b92da258a480284dcc15a518ea570072329a31dErik    public static void checkForDuplicateNames(
5127b92da258a480284dcc15a518ea570072329a31dErik            Map<String, Boolean> isDuplicateName, Cursor cursor, int nameIndex) {
513ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        isDuplicateName.clear();
514ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        cursor.moveToPosition(-1);
515ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        while (cursor.moveToNext()) {
516ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            String displayName = cursor.getString(nameIndex);
517ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            // Set it to true if we've seen this name before, false otherwise
518ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            if (displayName != null) {
519ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan                isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
520ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan            }
521ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan        }
522ff6be831fc682374be6b78c13ecf5daca81f86d9Michael Chan    }
5239138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
5249138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
5259138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * Null-safe object comparison
5267b92da258a480284dcc15a518ea570072329a31dErik     *
5279138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s1
5289138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @param s2
5299138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     * @return
5309138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang     */
5319138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public static boolean equals(Object o1, Object o2) {
5329138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return o1 == null ? o2 == null : o1.equals(o2);
5339138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    }
534b60218a31d948ea0a549daf6464063d20b48421fMichael Chan
53563cd053150e00fde045b019dbe0f48b8a9ed3559Erik    public static void setAllowWeekForDetailView(boolean allowWeekView) {
536b60218a31d948ea0a549daf6464063d20b48421fMichael Chan        mAllowWeekForDetailView  = allowWeekView;
537b60218a31d948ea0a549daf6464063d20b48421fMichael Chan    }
53863cd053150e00fde045b019dbe0f48b8a9ed3559Erik
53963cd053150e00fde045b019dbe0f48b8a9ed3559Erik    public static boolean getAllowWeekForDetailView() {
54063cd053150e00fde045b019dbe0f48b8a9ed3559Erik        return mAllowWeekForDetailView;
54163cd053150e00fde045b019dbe0f48b8a9ed3559Erik    }
5420b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson
5430b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson    public static boolean isMultiPaneConfiguration (Context c) {
5440b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson        return (c.getResources().getConfiguration().screenLayout &
5450b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson                Configuration.SCREENLAYOUT_SIZE_XLARGE) != 0;
5460b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson    }
547ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson
548ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson    public static boolean getConfigBool(Context c, int key) {
549ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson        return c.getResources().getBoolean(key);
550ff5c4345f794ec12b0a92f284434ddc1c88ff3a8Isaac Katzenelson    }
55182400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
55282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
55371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     /**
55472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * This is a helper class for the createBusyBitSegments method
55572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The class contains information about a specific time that corresponds to either a start
55672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * of an event or an end of an event (or both):
55772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * 1. The time itself
55872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * 2 .The number of event starts and ends (number of starts - number of ends)
55972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     */
56082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
56172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson    private static class BusyBitsEventTime {
56282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
56372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public static final int EVENT_START = 1;
56472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public static final int EVENT_END = -1;
565c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson
56672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public int mTime; // in minutes
56772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // Number of events that start and end in this time (+1 for each start,
56872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // -1 for each end)
56972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public int mStartEndChanges;
57072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
57172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public BusyBitsEventTime(int t, int c) {
57272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            mTime = t;
57372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            mStartEndChanges = c;
574c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson        }
57572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
57672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public void addStart() {
57772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            mStartEndChanges++;
578c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson        }
579c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson
58072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        public void addEnd() {
58172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            mStartEndChanges--;
58272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
58372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson    }
58472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
58572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson    /**
58672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * Corrects segments that are overlapping.
58771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * The function makes sure the last segment inserted do not overlap with segments in the
58871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * segments arrays. It will compare the last inserted segment to last segment in both the
58971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * busy array and conflicting array and make corrections to segments if necessary.
59072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The function assumes an overlap could be only 1 pixel.
59172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The function removes segments if necessary
59272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * Segment size is from start to end (inclusive)
59372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     *
59471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @param segments segments an array of 2 float arrays. The first array will contain the
59571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        coordinates for drawing busy segments, the second will contain the coordinates for
59671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        drawing conflicting segments. The first cell in each array contains the number of
59771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        used cell so this method can be called again without overriding data,
59871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @param arrayIndex - index of the segments array that got the last segment
59971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @param prevSegmentInserted - an indicator of the type of the previous segment inserted. This
60071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *
60171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @return boolean telling the calling functions whether to add the last segment or not.
60271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *         The calling function should first insert a new segment to the array, call this
60371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *         function and when getting a "true" value in the return value, update the counter of
60471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *         the array to indicate a new segment (Add 4 to the counter in cell 0).
60572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     */
60672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
60771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int START_PIXEL_Y = 1;        // index of pixel locations in a coordinates set
60871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int END_PIXEL_Y = 3;
60971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int BUSY_ARRAY_INDEX = 0;
61071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int CONFLICT_ARRAY_INDEX = 1;
61171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int COUNTER_INDEX = 0;
61272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
61371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int NO_PREV_INSERTED = 0;    // possible status of previous segment insertion
61471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int BUSY_PREV_INSERTED = 1;
61571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    static final int CONFLICT_PREV_INSERTED = 2;
61672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
61772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
61871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    public static boolean correctOverlappingSegment(float[][] segments,
61971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int arrayIndex, int prevSegmentInserted) {
62071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
62171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        if (prevSegmentInserted == NO_PREV_INSERTED) {
62271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // First segment - add it
62371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return true;
62472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
62571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
62671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Previous insert and this one are to the busy array
62771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        if (prevSegmentInserted == BUSY_PREV_INSERTED && arrayIndex == BUSY_ARRAY_INDEX) {
62871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
62971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Index of last and previously inserted segment
63071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iLast = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX];
63171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iPrev = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX] - 4;
63271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
63371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments do not overlap - add the new one
63471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] <
63571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]) {
63671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                return true;
63771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            }
63871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
63971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments overlap - merge them
64071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] =
64171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[BUSY_ARRAY_INDEX][iLast + END_PIXEL_Y];
64271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return false;
64372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
64472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
64571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Previous insert was to the busy array and this one is to the conflict array
64671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        if (prevSegmentInserted == BUSY_PREV_INSERTED && arrayIndex == CONFLICT_ARRAY_INDEX) {
64771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
64871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Index of last and previously inserted segment
64971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iLast = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX];
65071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iPrev = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX] - 4;
65171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
65271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments do not overlap - add the new one
65371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] <
65471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[CONFLICT_ARRAY_INDEX][iLast + START_PIXEL_Y]) {
65571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                return true;
65672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
65771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
65871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments overlap - truncate the end of the last busy segment
65971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // if it disappears , remove it
66071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y]--;
66171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[BUSY_ARRAY_INDEX][iPrev + END_PIXEL_Y] <
66271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[BUSY_ARRAY_INDEX][iPrev + START_PIXEL_Y]) {
66371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                segments[BUSY_ARRAY_INDEX] [COUNTER_INDEX] -= 4;
66472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
66571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return true;
66671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        }
66771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Previous insert was to the conflict array and this one is to the busy array
66871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        if (prevSegmentInserted == CONFLICT_PREV_INSERTED && arrayIndex == BUSY_ARRAY_INDEX) {
66971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
67071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Index of last and previously inserted segment
67171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iLast = 1 + (int) segments[BUSY_ARRAY_INDEX][COUNTER_INDEX];
67271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iPrev = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX] - 4;
67371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
67471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments do not overlap - add the new one
67571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] <
67671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]) {
67771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                return true;
67872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
67971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
68071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments overlap - truncate the new busy segment , if it disappears , do not
68171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // insert it
68271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y]++;
68371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[BUSY_ARRAY_INDEX][iLast + START_PIXEL_Y] >
68471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                segments[BUSY_ARRAY_INDEX][iLast + END_PIXEL_Y]) {
68571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                return false;
68671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            }
68771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return true;
68871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
68972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
69071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Previous insert and this one are to the conflict array
69171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        if (prevSegmentInserted == CONFLICT_PREV_INSERTED && arrayIndex == CONFLICT_ARRAY_INDEX) {
69271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
69371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Index of last and previously inserted segment
69471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iLast = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX];
69571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int iPrev = 1 + (int) segments[CONFLICT_ARRAY_INDEX][COUNTER_INDEX] - 4;
69682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
69771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments do not overlap - add the new one
69871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] <
69971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[CONFLICT_ARRAY_INDEX][iLast + START_PIXEL_Y]) {
70071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                return true;
70171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            }
70271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
70371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Segments overlap - merge them
70471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            segments[CONFLICT_ARRAY_INDEX][iPrev + END_PIXEL_Y] =
70571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    segments[CONFLICT_ARRAY_INDEX][iLast + END_PIXEL_Y];
70671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return false;
70771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        }
70871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Unknown state , complain
70971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        Log.wtf(TAG, "Unkown state in correctOverlappingSegment: prevSegmentInserted = " +
71071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                prevSegmentInserted + " arrayIndex = " + arrayIndex);
71171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        return false;
71271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    }
71372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
71472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson    /**
71572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * Converts a list of events to a list of busy segments to draw.
71672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * Assumes list is ordered according to start time of events
71772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The function processes events of a specific day only or part of that day
71872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     *
71972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The algorithm goes over all the events and creates an ordered list of times.
72072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * Each item on the list corresponds to a time where an event started,ended or both.
72172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The item has a count of how many events started and how many events ended at that time.
72272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * In the second stage, the algorithm go over the list of times and finds what change happened
72371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * at each time. A change can be a switch between either of the free time/busy time/conflicting
72472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * time. Every time a change happens, the algorithm creates a segment (in pixels) to be
72571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * displayed with the relevant status (free/busy/conflicting).
72672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * The algorithm also checks if segments overlap and truncates one of them if needed.
72772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     *
72872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param startPixel defines the start of the draw area
72972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param endPixel defines the end of the draw area
73071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @param xPixel the middle X position of the draw area
73172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param startTimeMinute start time (in minutes) of the time frame to be displayed as busy bits
73272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param endTimeMinute end time (in minutes) of the time frame to be displayed as busy bits
73372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param julianDay the day of the time frame
73472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     * @param daysEvents - a list of events that took place in the specified day (including
73572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     *                     recurring events, events that start before the day and/or end after
73672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     *                     the day
73771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     * @param segments an array of 2 float arrays. The first array will contain the coordinates
73871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        for drawing busy segments, the second will contain the coordinates for drawing
73971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        conflicting segments. The first cell in each array contains the number of used cell
74071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *        so this method can be called again without overriding data,
74171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson     *
74272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson     */
74372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
74471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson    public static void createBusyBitSegments(int startPixel, int endPixel,
74571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int xPixel, int startTimeMinute, int endTimeMinute, int julianDay,
74671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            ArrayList<Event> daysEvents, float [] [] segments) {
74772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
74872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // No events or illegal parameters , do nothing
74972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
75072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        if (daysEvents == null || daysEvents.size() == 0 || startPixel >= endPixel ||
75172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                startTimeMinute < 0 || startTimeMinute > 24 * 60 || endTimeMinute < 0 ||
75271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                endTimeMinute > 24 * 60 || startTimeMinute >= endTimeMinute ||
75371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                segments == null || segments [0] == null || segments [1] == null) {
75472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            Log.wtf(TAG, "Illegal parameter in createBusyBitSegments,  " +
75572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    "daysEvents = " + daysEvents + " , " +
75672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    "startPixel = " + startPixel + " , " +
75772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    "endPixel = " + endPixel + " , " +
75872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    "startTimeMinute = " + startTimeMinute + " , " +
75971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    "endTimeMinute = " + endTimeMinute + " , " +
76071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    "segments" + segments);
76171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return;
76272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
76372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
76472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // Go over all events and create a sorted list of times that include all
76572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // the start and end times of all events.
76672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
76772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        ArrayList<BusyBitsEventTime> times = new ArrayList<BusyBitsEventTime>();
76872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
76972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        Iterator<Event> iter = daysEvents.iterator();
77072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // Pointer to the search start in the "times" list. It prevents searching from the beginning
77172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // of the list for each event. It is updated every time a new start time is inserted into
77272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // the times list, since the events are time ordered, there is no point on searching before
77372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // the last start time that was inserted
77472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        int initialSearchIndex = 0;
77582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson        while (iter.hasNext()) {
77682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            Event event = iter.next();
77782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
77872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Take into account the start and end day. This is important for events that span
77972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // multiple days.
78072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            int eStart = event.startTime - (julianDay - event.startDay) * 24 * 60;
78172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            int eEnd = event.endTime + (event.endDay - julianDay) * 24 * 60;
78282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
78372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Skip all day events, and events that are not in the time frame
78472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (event.drawAsAllday() || eStart >= endTimeMinute || eEnd <= startTimeMinute) {
78582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson                continue;
78682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            }
78782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
788c18dd7aea8c8ee06dd34f268ea9e0e9e7c235b7fIsaac Katzenelson            // If event spans before or after start or end time , truncate it
78972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // because we care only about the time span that is passed to the function
79072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (eStart < startTimeMinute) {
79172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                eStart = startTimeMinute;
79272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
79372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (eEnd > endTimeMinute) {
79472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                eEnd = endTimeMinute;
79582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            }
79672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Skip events that are zero length
79772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (eStart == eEnd) {
79872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                continue;
79982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            }
80082400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
80172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // First event , just put it in the "times" list
80272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (times.size() == 0) {
80372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                BusyBitsEventTime es = new BusyBitsEventTime(eStart, BusyBitsEventTime.EVENT_START);
80472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                BusyBitsEventTime ee = new BusyBitsEventTime(eEnd, BusyBitsEventTime.EVENT_END);
80572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                times.add(es);
80672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                times.add(ee);
80782400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson                continue;
80882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            }
80982400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
81072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Insert start and end times of event in "times" list.
81172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Loop through the "times" list and put the event start and ends times in the correct
81272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // place.
81372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            boolean startInserted = false;
81472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            boolean endInserted = false;
81572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            int i = initialSearchIndex; // Skip times that are before the event time
81672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Two pointers for looping through the "times" list. Current item and next item.
81772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            int t1, t2;
81872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            do {
81972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                t1 = times.get(i).mTime;
82072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                t2 = times.get(i + 1).mTime;
82172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                if (!startInserted) {
82272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // Start time equals an existing item in the "times" list, just update the
82372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // starts count of the specific item
82472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    if (eStart == t1) {
82572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.get(i).addStart();
82672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        initialSearchIndex = i;
82772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        startInserted = true;
82872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    } else if (eStart == t2) {
82972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.get(i + 1).addStart();
83072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        initialSearchIndex = i + 1;
83172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        startInserted = true;
83272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    } else if (eStart > t1 && eStart < t2) {
83372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        // The start time is between the times of the current item and next item:
83472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        // insert a new start time in between the items.
83572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        BusyBitsEventTime e = new BusyBitsEventTime(eStart,
83672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                                BusyBitsEventTime.EVENT_START);
83772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.add(i + 1, e);
83872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        initialSearchIndex = i + 1;
83972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        t2 = eStart;
84072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        startInserted = true;
84172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    }
84282400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson                }
84372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                if (!endInserted) {
84472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // End time equals an existing item in the "times" list, just update the
84572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // ends count of the specific item
84672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    if (eEnd == t1) {
84772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.get(i).addEnd();
84872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        endInserted = true;
84972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    } else if (eEnd == t2) {
85072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.get(i + 1).addEnd();
85172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        endInserted = true;
85272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    } else if (eEnd > t1 && eEnd < t2) {
85372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        // The end time is between the times of the current item and next item:
85472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        // insert a new end time in between the items.
85572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        BusyBitsEventTime e = new BusyBitsEventTime(eEnd,
85672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                                BusyBitsEventTime.EVENT_END);
85772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        times.add(i + 1, e);
85872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        t2 = eEnd;
85972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                        endInserted = true;
86072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    }
86172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                }
86272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                i++;
86372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            } while (!endInserted && i + 1 < times.size());
86472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
86572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            // Deal with the last event if not inserted in the list
86672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (!startInserted) {
86772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                BusyBitsEventTime e = new BusyBitsEventTime(eStart, BusyBitsEventTime.EVENT_START);
86872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                times.add(e);
86972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                initialSearchIndex = times.size() - 1;
87072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
87172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            if (!endInserted) {
87272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                BusyBitsEventTime e = new BusyBitsEventTime(eEnd, BusyBitsEventTime.EVENT_END);
87372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                times.add(e);
87482400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson            }
87582400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson        }
87682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson
87772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // No events , return
87872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        if (times.size() == 0) {
87971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            return;
88072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        }
88172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
88271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Loop through the created "times" list and find busy time segments and conflicting
88371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // segments. In the loop, keep the status of time (free/busy/conflicting) and the time
88472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // of when last status started. When there is a change in the status, create a segment with
88572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // the previous status from the time of the last status started until the time of the
88672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // current change.
88771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // The loop keeps a count of how many events are conflicting. Zero means free time, one
88871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // means a busy time and more than one means conflicting time. The count is updated by
88972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        // the number of starts and ends from the items in the "times" list. A change is a switch
89071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // from free/busy/conflicting status to a different one.
89172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
89272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
89372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        int segmentStartTime = 0;  // default start time
89471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        int conflictingCount = 0;   // assume starting with free time
89572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        int pixelSize = endPixel - startPixel;
89672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        int timeFrame = endTimeMinute - startTimeMinute;
89771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        int prevSegmentInserted = NO_PREV_INSERTED;
89871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
89971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson
90071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // Arrays are preallocated by the calling code, the first cell in the
90171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // array is the number
90271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        // of already occupied cells.
90371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        float[] busySegments = segments[BUSY_ARRAY_INDEX];
90471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        float[] conflictSegments = segments[CONFLICT_ARRAY_INDEX];
90572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
90672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        Iterator<BusyBitsEventTime> tIter = times.iterator();
90772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson        while (tIter.hasNext()) {
90872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            BusyBitsEventTime t = tIter.next();
90971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // Get the new count of conflicting events
91071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            int newCount = conflictingCount + t.mStartEndChanges;
91172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson
91271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // No need for a new segment because the free/busy/conflicting
91371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            // status didn't change
91471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (conflictingCount == newCount || (conflictingCount >= 2 && newCount >= 2)) {
91571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictingCount = newCount;
91672a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                continue;
91772a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
91871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            if (conflictingCount == 0 && newCount == 1) {
91972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                // A busy time started - start a new segment
92072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                if (segmentStartTime != 0) {
92172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // Unknown status, blow up
92272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    Log.wtf(TAG, "Unknown state in createBusyBitSegments, segmentStartTime = " +
92372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                            segmentStartTime + ", nolc = " + newCount);
92472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                }
92572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = t.mTime;
92671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            } else if (conflictingCount == 0 && newCount >= 2) {
92771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // An conflicting time started - start a new segment
92872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                if (segmentStartTime != 0) {
92972a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    // Unknown status, blow up
93072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                    Log.wtf(TAG, "Unknown state in createBusyBitSegments, segmentStartTime = " +
93172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                            segmentStartTime + ", nolc = " + newCount);
93272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                }
93372a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = t.mTime;
93471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            } else if (conflictingCount == 1 && newCount >= 2) {
93571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // A busy time ended and conflicting segment started,
93671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Save busy segment and start conflicting segment
93771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                int iBusy = 1 + (int) busySegments[COUNTER_INDEX];
93871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = xPixel;
93971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = (segmentStartTime - startTimeMinute) *
94071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
94171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = xPixel;
94271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = (t.mTime - startTimeMinute) *
94371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
94471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Update the segments counter only after overlap correction
94571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                if (correctOverlappingSegment(segments, BUSY_ARRAY_INDEX, prevSegmentInserted)) {
94671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    busySegments[COUNTER_INDEX] += 4;
94771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                }
94872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = t.mTime;
94971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                prevSegmentInserted = BUSY_PREV_INSERTED;
95071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            } else if (conflictingCount >= 2 && newCount == 1) {
95171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // A conflicting time ended and busy segment started.
95271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Save conflicting segment and start busy segment
95371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                int iConflicting = 1 + (int) conflictSegments[COUNTER_INDEX];
95471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = xPixel;
95571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = (segmentStartTime - startTimeMinute) *
95671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
95771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = xPixel;
95871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = (t.mTime - startTimeMinute) *
95971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
96071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Update the segments counter only after overlap correction
96171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                if (correctOverlappingSegment(segments, CONFLICT_ARRAY_INDEX,
96271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        prevSegmentInserted)) {
96371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    conflictSegments[COUNTER_INDEX] += 4;
96471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                }
96572a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = t.mTime;
96671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                prevSegmentInserted = CONFLICT_PREV_INSERTED;
96771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            } else if (conflictingCount >= 2 && newCount == 0) {
96871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // An conflicting segment ended, and a free time segment started
96971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Save conflicting segment
97071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                int iConflicting = 1 + (int) conflictSegments[COUNTER_INDEX];
97171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = xPixel;
97271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = (segmentStartTime - startTimeMinute) *
97371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
97471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = xPixel;
97571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                conflictSegments[iConflicting++] = (t.mTime - startTimeMinute) *
97671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
97771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Update the segments counter only after overlap correction
97871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                if (correctOverlappingSegment(segments, CONFLICT_ARRAY_INDEX,
97971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        prevSegmentInserted)) {
98071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    conflictSegments[COUNTER_INDEX] += 4;
98171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                }
98272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = 0;
98371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                prevSegmentInserted = CONFLICT_PREV_INSERTED;
98471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            } else if (conflictingCount == 1 && newCount == 0) {
98571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // A busy segment ended, and a free time segment started, save
98671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // busy segment
98771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                int iBusy = 1 + (int) busySegments[COUNTER_INDEX];
98871b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = xPixel;
98971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = (segmentStartTime - startTimeMinute) *
99071b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
99171b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = xPixel;
99271b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                busySegments[iBusy++] = (t.mTime - startTimeMinute) *
99371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        pixelSize / timeFrame + startPixel;
99471b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                // Update the segments counter only after overlap correction
99571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                if (correctOverlappingSegment(segments, BUSY_ARRAY_INDEX, prevSegmentInserted)) {
99671b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                    busySegments[COUNTER_INDEX] += 4;
99771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                }
99872a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                segmentStartTime = 0;
99971b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                prevSegmentInserted = BUSY_PREV_INSERTED;
100072a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            } else {
100172a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                // Unknown status, blow up
100272a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson                Log.wtf(TAG, "Unknown state in createBusyBitSegments: time = " + t.mTime +
100371b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson                        " , olc = " + conflictingCount + " nolc = " + newCount);
100472a9459e1f4cec02ad9e8dbdf824d66920b762eeIsaac Katzenelson            }
100571b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson            conflictingCount = newCount; // Update count
100682400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson        }
100771b9ce3a20ebaff8f7e40fc0e5ec2a388bcc394cIsaac Katzenelson        return;
100882400dd70331df7885dd59b809c4bc0667046320Isaac Katzenelson    }
1009146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
1010