16c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu/* 26c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Copyright (C) 2014 The Android Open Source Project 36c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 46c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Licensed under the Apache License, Version 2.0 (the "License"); 56c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * you may not use this file except in compliance with the License. 66c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * You may obtain a copy of the License at 76c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 86c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * http://www.apache.org/licenses/LICENSE-2.0 96c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 106c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Unless required by applicable law or agreed to in writing, software 116c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * distributed under the License is distributed on an "AS IS" BASIS, 126c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * See the License for the specific language governing permissions and 146c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * limitations under the License. 156c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 166c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 176c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hupackage com.android.exchange.service; 186c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 19451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.app.AlarmManager; 20451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.app.PendingIntent; 216c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport android.app.Service; 22451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.content.ContentResolver; 23c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Leeimport android.content.Context; 246c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport android.content.Intent; 25451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.os.Bundle; 26451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.os.SystemClock; 276c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport android.support.v4.util.LongSparseArray; 28451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport android.text.format.DateUtils; 296c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 30c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Leeimport com.android.emailcommon.provider.Account; 31451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport com.android.emailcommon.provider.EmailContent; 32451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdonimport com.android.emailcommon.provider.Mailbox; 336c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport com.android.exchange.Eas; 34c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Leeimport com.android.exchange.eas.EasPing; 356c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport com.android.mail.utils.LogUtils; 366c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 376c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport java.util.concurrent.locks.Condition; 386c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport java.util.concurrent.locks.Lock; 396c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Huimport java.util.concurrent.locks.ReentrantLock; 406c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 416c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu/** 426c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Bookkeeping for handling synchronization between pings and other sync related operations. 436c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * "Ping" refers to a hanging POST or GET that is used to receive push notifications. Ping is 446c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * the term for the Exchange command, but this code should be generic enough to be extended to IMAP. 456c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 466c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Basic rules of how these interact (note that all rules are per account): 476c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Only one operation (ping or other active sync operation) may run at a time. 486c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - For shorthand, this class uses "sync" to mean "non-ping operation"; most such operations are 496c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * sync ops, but some may not be (e.g. EAS Settings). 506c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Syncs can come from many sources concurrently; this class must serialize them. 516c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 526c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WHEN A SYNC STARTS: 536c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If nothing is running, proceed. 546c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If something is already running: wait until it's done. 556c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If the running thing is a ping task: interrupt it. 566c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 576c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WHEN A SYNC ENDS: 586c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If there are waiting syncs: signal one to proceed. 596c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If there are no waiting syncs and this account is configured for push: start a ping. 606c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Otherwise: This account is now idle. 616c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 626c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WHEN A PING TASK ENDS: 636c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - A ping task loops until either it's interrupted by a sync (in which case, there will be one or 646c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * more waiting syncs when the ping terminates), or encounters an error. 656c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If there are waiting syncs, and we were interrupted: signal one to proceed. 666c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If there are waiting syncs, but the ping terminated with an error: TODO: How to handle? 676c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If there are no waiting syncs and this account is configured for push: This means the ping task 686c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * was terminated due to an error. Handle this by sending a sync request through the SyncManager 696c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * that doesn't actually do any syncing, and whose only effect is to restart the ping. 706c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Otherwise: This account is now idle. 716c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 726c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WHEN AN ACCOUNT WANTS TO START OR CHANGE ITS PUSH BEHAVIOR: 736c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If nothing is running, start a new ping task. 746c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If a ping task is currently running, restart it with the new settings. 756c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If a sync is currently running, do nothing. 766c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * 776c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * WHEN AN ACCOUNT WANTS TO STOP GETTING PUSH: 786c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If nothing is running, do nothing. 796c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - If a ping task is currently running, interrupt it. 806c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 816c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hupublic class PingSyncSynchronizer { 826c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 836c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private static final String TAG = Eas.LOG_TAG; 846c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 85451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon private static final long SYNC_ERROR_BACKOFF_MILLIS = DateUtils.MINUTE_IN_MILLIS; 86451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon 87451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon // Enable this to make pings get automatically renewed every hour. This 88451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon // should not be needed, but if there is a software error that results in 89451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon // the ping being lost, this is a fallback to make sure that messages are 90451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon // not delayed more than an hour. 9129df1a2f769cefedf8ec84403b5dc1384d3cb551Martin Hibdon private static final boolean SCHEDULE_KICK = true; 92451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon private static final long KICK_SYNC_INTERVAL_SECONDS = 93451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon DateUtils.HOUR_IN_MILLIS / DateUtils.SECOND_IN_MILLIS; 94451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon 956c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 966c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * This class handles bookkeeping for a single account. 976c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 981e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon private class AccountSyncState { 996c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** The currently running {@link PingTask}, or null if we aren't in the middle of a Ping. */ 1006c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private PingTask mPingTask; 1016c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 1021e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // Values for mPushEnabled. 1031e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon public static final int PUSH_UNKNOWN = 0; 1041e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon public static final int PUSH_ENABLED = 1; 1051e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon public static final int PUSH_DISABLED = 2; 1061e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon 1076c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 108468ff529b5c80605a62d6fc7ecf87a8db46ea366Yu Ping Hu * Tracks whether this account wants to get push notifications, based on calls to 109468ff529b5c80605a62d6fc7ecf87a8db46ea366Yu Ping Hu * {@link #pushModify} and {@link #pushStop} (i.e. it tracks the last requested push state). 110468ff529b5c80605a62d6fc7ecf87a8db46ea366Yu Ping Hu */ 1111e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon private int mPushEnabled; 112468ff529b5c80605a62d6fc7ecf87a8db46ea366Yu Ping Hu 113468ff529b5c80605a62d6fc7ecf87a8db46ea366Yu Ping Hu /** 1146c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * The number of syncs that are blocked waiting for the current operation to complete. 1156c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Unlike Pings, sync operations do not start their own tasks and are assumed to run in 1166c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * whatever thread calls into this class. 1176c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 1186c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private int mSyncCount; 1196c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 1206c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** The condition on which to block syncs that need to wait. */ 1216c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private Condition mCondition; 1226c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 12347b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon /** The accountId for this accountState, used for logging */ 12447b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon private long mAccountId; 12547b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon 12647b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon public AccountSyncState(final Lock lock, final long accountId) { 1276c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mPingTask = null; 1281e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // We don't yet have enough information to know whether or not push should be enabled. 1291e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // We need to look up the account and it's folders, which won't yet exist for a newly 1301e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // created account. 1311e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon mPushEnabled = PUSH_UNKNOWN; 1326c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mSyncCount = 0; 1336c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mCondition = lock.newCondition(); 13447b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon mAccountId = accountId; 1356c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1366c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 1376c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 1386c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Update bookkeeping for a new sync: 1396c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Stop the Ping if there is one. 1406c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * - Wait until there's nothing running for this account before proceeding. 1416c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 1426c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu public void syncStart() { 1436c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu ++mSyncCount; 1446c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mPingTask != null) { 1456c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // Syncs are higher priority than Ping -- terminate the Ping. 14647b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS Sync is pre-empting a ping acct:%d", mAccountId); 1476c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mPingTask.stop(); 1486c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1496c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mPingTask != null || mSyncCount > 1) { 1506c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // There’s something we need to wait for before we can proceed. 1516c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 15247b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS Sync needs to wait: Ping: %s, Pending tasks: %d acct: %d", 15347b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon mPingTask != null ? "yes" : "no", mSyncCount, mAccountId); 1546c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mCondition.await(); 1556c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } catch (final InterruptedException e) { 1566c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // TODO: Handle this properly. Not catching it might be the right answer. 15747b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS InterruptedException acct:%d", mAccountId); 1586c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1596c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1606c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1616c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 1626c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 1636c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Update bookkeeping when a sync completes. This includes signaling pending ops to 1646c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * go ahead, or starting the ping if appropriate and there are no waiting ops. 1656c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @return Whether this account is now idle. 1666c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 167451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon public boolean syncEnd(final boolean lastSyncHadError, final Account account, 168451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final PingSyncSynchronizer synchronizer) { 1696c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu --mSyncCount; 1706c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mSyncCount > 0) { 17147b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS Signalling a pending sync to proceed acct:%d.", 17247b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon account.getId()); 1736c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mCondition.signal(); 1746c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return false; 1756c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } else { 1761e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon if (mPushEnabled == PUSH_UNKNOWN) { 1771e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon LogUtils.i(TAG, "PSS push enabled is unknown"); 1781e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon mPushEnabled = (EasService.pingNeededForAccount(mService, account) ? 1791e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon PUSH_ENABLED : PUSH_DISABLED); 1801e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon } 1811e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon if (mPushEnabled == PUSH_ENABLED) { 182451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon if (lastSyncHadError) { 18347b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS last sync had error, scheduling delayed ping acct:%d.", 18447b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon account.getId()); 18553d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon scheduleDelayedPing(synchronizer.getContext(), account); 186451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon return true; 187451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon } else { 18847b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS last sync succeeded, starting new ping acct:%d.", 18947b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon account.getId()); 190451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final android.accounts.Account amAccount = 191451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon new android.accounts.Account(account.mEmailAddress, 192451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE); 193451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon mPingTask = new PingTask(synchronizer.getContext(), account, amAccount, 194451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon synchronizer); 195451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon mPingTask.start(); 196451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon return false; 197451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon } 1986c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 1996c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 20047b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS no push enabled acct:%d.", account.getId()); 2016c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return true; 2026c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2036c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 2046c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 2056c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Update bookkeeping when the ping task terminates, including signaling any waiting ops. 2066c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @return Whether this account is now idle. 2076c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 208451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon private boolean pingEnd(final android.accounts.Account amAccount) { 2096c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mPingTask = null; 2106c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mSyncCount > 0) { 21147b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pingEnd, syncs still in progress acct:%d.", mAccountId); 2126c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mCondition.signal(); 2136c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return false; 2146c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } else { 2151e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon if (mPushEnabled == PUSH_ENABLED || mPushEnabled == PUSH_UNKNOWN) { 2161e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon if (mPushEnabled == PUSH_UNKNOWN) { 2171e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // This should not occur. If mPushEnabled is unknown, we should not 2181e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // have started a ping. Still, we'd rather err on the side of restarting 2191e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // the ping, so log an error and request a new ping. Eventually we should 2201e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // do a sync, and then we'll correctly initialize mPushEnabled in 2211e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon // syncEnd(). 2221e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon LogUtils.e(TAG, "PSS pingEnd, with mPushEnabled UNKNOWN?"); 2231e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon } 22447b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pingEnd, starting new ping acct:%d.", mAccountId); 225c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee /** 226c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee * This situation only arises if we encountered some sort of error that 227c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee * stopped our ping but not due to a sync interruption. In this scenario 228c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee * we'll leverage the SyncManager to request a push only sync that will 229c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee * restart the ping when the time is right. */ 230c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee EasPing.requestPing(amAccount); 2316c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return false; 2326c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2336c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 23447b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pingEnd, no longer need ping acct:%d.", mAccountId); 2356c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return true; 2366c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2376c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 238451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon private void scheduleDelayedPing(final Context context, 23953d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon final Account account) { 24047b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS Scheduling a delayed ping acct:%d.", account.getId()); 24153d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon final Intent intent = new Intent(context, EasService.class); 242451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon intent.setAction(Eas.EXCHANGE_SERVICE_INTENT_ACTION); 24353d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon intent.putExtra(EasService.EXTRA_START_PING, true); 24453d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon intent.putExtra(EasService.EXTRA_PING_ACCOUNT, account); 24553d15f1321d19432c88de34e57218a5f51eaf3dcMartin Hibdon 246451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final PendingIntent pi = PendingIntent.getService(context, 0, intent, 247451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon PendingIntent.FLAG_ONE_SHOT); 248451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final AlarmManager am = (AlarmManager)context.getSystemService( 249451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon Context.ALARM_SERVICE); 250451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final long atTime = SystemClock.elapsedRealtime() + SYNC_ERROR_BACKOFF_MILLIS; 251451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi); 252451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon } 253451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon 2546c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 2556c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Modifies or starts a ping for this account if no syncs are running. 2566c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 257c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee public void pushModify(final Account account, final PingSyncSynchronizer synchronizer) { 25847b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(LogUtils.TAG, "PSS pushModify acct:%d", account.getId()); 2591e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon mPushEnabled = PUSH_ENABLED; 260451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final android.accounts.Account amAccount = 261451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon new android.accounts.Account(account.mEmailAddress, 262451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE); 2636c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mSyncCount == 0) { 2646c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mPingTask == null) { 2656c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // No ping, no running syncs -- start a new ping. 26647b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(LogUtils.TAG, "PSS starting ping task acct:%d", account.getId()); 267c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee mPingTask = new PingTask(synchronizer.getContext(), account, amAccount, 268c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee synchronizer); 269c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee mPingTask.start(); 2706c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } else { 2716c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // Ping is already running, so tell it to restart to pick up any new params. 27247b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(LogUtils.TAG, "PSS restarting ping task acct:%d", account.getId()); 2736c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mPingTask.restart(); 2746c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 27547b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon } else { 27647b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(LogUtils.TAG, "PSS syncs still in progress acct:%d", account.getId()); 2776c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 278451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon if (SCHEDULE_KICK) { 279451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon final Bundle extras = new Bundle(1); 280451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon extras.putBoolean(Mailbox.SYNC_EXTRA_PUSH_ONLY, true); 281451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon ContentResolver.addPeriodicSync(amAccount, EmailContent.AUTHORITY, extras, 282451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon KICK_SYNC_INTERVAL_SECONDS); 283451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon } 2846c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2856c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 2866c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 2876c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Stop the currently running ping. 2886c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 2896c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu public void pushStop() { 29047b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(LogUtils.TAG, "PSS pushStop acct:%d", mAccountId); 2911e2a913eb7bd5b30ad4098582c31ba9c6b40efb5Martin Hibdon mPushEnabled = PUSH_DISABLED; 2926c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mPingTask != null) { 2936c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mPingTask.stop(); 2946c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2956c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2966c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 2976c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 2986c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 2996c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Lock for access to {@link #mAccountStateMap}, also used to create the {@link Condition}s for 3006c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * each Account. 3016c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 3026c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private final ReentrantLock mLock; 3036c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 3046c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 3056c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Map from account ID -> {@link AccountSyncState} for accounts with a running operation. 3066c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * An account is in this map only when this account is active, i.e. has a ping or sync running 3076c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * or pending. If an account is not in the middle of a sync and is not configured for push, 3086c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * it will not be here. This allows to use emptiness of this map to know whether the service 3096c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * needs to be running, and is also handy when debugging. 3106c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 3116c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private final LongSparseArray<AccountSyncState> mAccountStateMap; 3126c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 3136c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** The {@link Service} that this object is managing. */ 3146c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private final Service mService; 3156c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 3166c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu public PingSyncSynchronizer(final Service service) { 3176c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock = new ReentrantLock(); 3186c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mAccountStateMap = new LongSparseArray<AccountSyncState>(); 3196c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mService = service; 3206c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3216c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 322c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee public Context getContext() { 323c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee return mService; 324c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee } 325c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee 3266c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 3276c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Gets the {@link AccountSyncState} for an account. 3286c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * The caller must hold {@link #mLock}. 3296c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @param accountId The id for the account we're interested in. 3306c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @param createIfNeeded If true, create the account state if it's not already there. 3316c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @return The {@link AccountSyncState} for that account, or null if the account is idle and 3326c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * createIfNeeded is false. 3336c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 3346c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private AccountSyncState getAccountState(final long accountId, final boolean createIfNeeded) { 3356c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu assert mLock.isHeldByCurrentThread(); 3366c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu AccountSyncState state = mAccountStateMap.get(accountId); 3376c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (state == null && createIfNeeded) { 33847b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS adding account state for acct:%d", accountId); 33947b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon state = new AccountSyncState(mLock, accountId); 3406c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mAccountStateMap.put(accountId, state); 3416c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu // TODO: Is this too late to startService? 3426c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mAccountStateMap.size() == 1) { 3436c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu LogUtils.i(TAG, "PSS added first account, starting service"); 3446c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mService.startService(new Intent(mService, mService.getClass())); 3456c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3466c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3476c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return state; 3486c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3496c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 3506c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu /** 3516c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * Remove an account from the map. If this was the last account, then also stop this service. 3526c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * The caller must hold {@link #mLock}. 3536c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu * @param accountId The id for the account we're removing. 3546c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu */ 3556c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu private void removeAccount(final long accountId) { 3566c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu assert mLock.isHeldByCurrentThread(); 35747b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS removing account state for acct:%d", accountId); 3586c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mAccountStateMap.delete(accountId); 3596c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (mAccountStateMap.size() == 0) { 3606c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu LogUtils.i(TAG, "PSS removed last account; stopping service."); 3616c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mService.stopSelf(); 3626c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3636c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3646c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 3656c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu public void syncStart(final long accountId) { 3666c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.lock(); 3676c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 36847b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS syncStart for account acct:%d", accountId); 3696c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu final AccountSyncState accountState = getAccountState(accountId, true); 3706c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu accountState.syncStart(); 3716c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } finally { 3726c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.unlock(); 3736c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3746c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3756c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 376451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon public void syncEnd(final boolean lastSyncHadError, final Account account) { 3776c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.lock(); 3786c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 379c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee final long accountId = account.getId(); 38047b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS syncEnd for account acct:%d", account.getId()); 3816c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu final AccountSyncState accountState = getAccountState(accountId, false); 3826c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (accountState == null) { 3836c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu LogUtils.w(TAG, "PSS syncEnd for account %d but no state found", accountId); 3846c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return; 3856c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 386451160bfda22734f7b33106edfa4a6ce19b62121Martin Hibdon if (accountState.syncEnd(lastSyncHadError, account, this)) { 3876c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu removeAccount(accountId); 3886c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3896c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } finally { 3906c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.unlock(); 3916c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3926c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 3936c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 394c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee public void pingEnd(final long accountId, final android.accounts.Account amAccount) { 3956c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.lock(); 3966c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 39747b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pingEnd for account %d", accountId); 3986c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu final AccountSyncState accountState = getAccountState(accountId, false); 3996c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (accountState == null) { 4006c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu LogUtils.w(TAG, "PSS pingEnd for account %d but no state found", accountId); 4016c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu return; 4026c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 403c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee if (accountState.pingEnd(amAccount)) { 4046c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu removeAccount(accountId); 4056c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4066c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } finally { 4076c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.unlock(); 4086c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4096c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4106c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 411c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee public void pushModify(final Account account) { 4126c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.lock(); 4136c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 414c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee final long accountId = account.getId(); 41547b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pushModify acct:%d", accountId); 4166c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu final AccountSyncState accountState = getAccountState(accountId, true); 417c9e6e7587ac847c6b99d91097f8e1bc64e9e56daAnthony Lee accountState.pushModify(account, this); 4186c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } finally { 4196c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.unlock(); 4206c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4216c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4226c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu 4236c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu public void pushStop(final long accountId) { 4246c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.lock(); 4256c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu try { 42647b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS pushStop acct:%d", accountId); 4276c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu final AccountSyncState accountState = getAccountState(accountId, false); 4286c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu if (accountState != null) { 4296c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu accountState.pushStop(); 4306c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4316c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } finally { 4326c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu mLock.unlock(); 4336c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 4346c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu } 435dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu 436dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu /** 437dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu * Stops our service if our map contains no active accounts. 438dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu */ 439dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu public void stopServiceIfIdle() { 440dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mLock.lock(); 441dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu try { 44247b5e0eb42afd02cb933ee3ed0d6c917056b744dMartin Hibdon LogUtils.i(TAG, "PSS stopIfIdle"); 443dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu if (mAccountStateMap.size() == 0) { 444dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu LogUtils.i(TAG, "PSS has no active accounts; stopping service."); 445dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mService.stopSelf(); 446dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 447dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } finally { 448dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mLock.unlock(); 449dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 450dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 451dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu 452dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu /** 453dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu * Tells all running ping tasks to stop. 454dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu */ 455dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu public void stopAllPings() { 456dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mLock.lock(); 457dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu try { 458dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu for (int i = 0; i < mAccountStateMap.size(); ++i) { 459dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mAccountStateMap.valueAt(i).pushStop(); 460dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 461dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } finally { 462dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu mLock.unlock(); 463dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 464dd316c9ade8257b2489c78fa3eb2763c9042b5ddYu Ping Hu } 4656c4254903d2f42836c5b74a934e54441ccee6dbeYu Ping Hu} 466