Merge commit '7a1a203786f10b60393efdec606cea416aa99e16' into gingerbread-plus-aosp * commit '7a1a203786f10b60393efdec606cea416aa99e16': Handle correction of rejected Ping heartbeat
This commit is contained in:
commit
84f7d07d4f
src/com/android/exchange
tests/src/com/android/exchange
@ -153,10 +153,7 @@ public class EasSyncService extends AbstractSyncService {
|
||||
static private final int PING_MINUTES = 60; // in seconds
|
||||
static private final int PING_FUDGE_LOW = 10;
|
||||
static private final int PING_STARTING_HEARTBEAT = (8*PING_MINUTES)-PING_FUDGE_LOW;
|
||||
static private final int PING_MIN_HEARTBEAT = (5*PING_MINUTES)-PING_FUDGE_LOW;
|
||||
static private final int PING_MAX_HEARTBEAT = (17*PING_MINUTES)-PING_FUDGE_LOW;
|
||||
static private final int PING_HEARTBEAT_INCREMENT = 3*PING_MINUTES;
|
||||
static private final int PING_FORCE_HEARTBEAT = 2*PING_MINUTES;
|
||||
|
||||
// Maximum number of times we'll allow a sync to "loop" with MoreAvailable true before
|
||||
// forcing it to stop. This number has been determined empirically.
|
||||
@ -192,12 +189,18 @@ public class EasSyncService extends AbstractSyncService {
|
||||
private ArrayList<String> mPingChangeList;
|
||||
// The HttpPost in progress
|
||||
private volatile HttpPost mPendingPost = null;
|
||||
// Our heartbeat when we are waiting for ping boxes to be ready
|
||||
/*package*/ int mPingForceHeartbeat = 2*PING_MINUTES;
|
||||
// The minimum heartbeat we will send
|
||||
/*package*/ int mPingMinHeartbeat = (5*PING_MINUTES)-PING_FUDGE_LOW;
|
||||
// The maximum heartbeat we will send
|
||||
/*package*/ int mPingMaxHeartbeat = (17*PING_MINUTES)-PING_FUDGE_LOW;
|
||||
// The ping time (in seconds)
|
||||
private int mPingHeartbeat = PING_STARTING_HEARTBEAT;
|
||||
/*package*/ int mPingHeartbeat = PING_STARTING_HEARTBEAT;
|
||||
// The longest successful ping heartbeat
|
||||
private int mPingHighWaterMark = 0;
|
||||
// Whether we've ever lowered the heartbeat
|
||||
private boolean mPingHeartbeatDropped = false;
|
||||
/*package*/ boolean mPingHeartbeatDropped = false;
|
||||
// Whether a POST was aborted due to alarm (watchdog alarm)
|
||||
private boolean mPostAborted = false;
|
||||
// Whether a POST was aborted due to reset
|
||||
@ -1541,6 +1544,10 @@ public class EasSyncService extends AbstractSyncService {
|
||||
} catch (StaleFolderListException e) {
|
||||
// We break out if we get told about a stale folder list
|
||||
userLog("Ping interrupted; folder list requires sync...");
|
||||
} catch (IllegalHeartbeatException e) {
|
||||
// If we're sending an illegal heartbeat, reset either the min or the max to
|
||||
// that heartbeat
|
||||
resetHeartbeats(e.mLegalHeartbeat);
|
||||
} finally {
|
||||
Thread.currentThread().setName(threadName);
|
||||
}
|
||||
@ -1561,6 +1568,44 @@ public class EasSyncService extends AbstractSyncService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset either our minimum or maximum ping heartbeat to a heartbeat known to be legal
|
||||
* @param legalHeartbeat a known legal heartbeat (from the EAS server)
|
||||
*/
|
||||
/*package*/ void resetHeartbeats(int legalHeartbeat) {
|
||||
userLog("Resetting min/max heartbeat, legal = " + legalHeartbeat);
|
||||
// We are here because the current heartbeat (mPingHeartbeat) is invalid. Depending on
|
||||
// whether the argument is above or below the current heartbeat, we can infer the need to
|
||||
// change either the minimum or maximum heartbeat
|
||||
if (legalHeartbeat > mPingHeartbeat) {
|
||||
// The legal heartbeat is higher than the ping heartbeat; therefore, our minimum was
|
||||
// too low. We respond by raising either or both of the minimum heartbeat or the
|
||||
// force heartbeat to the argument value
|
||||
if (mPingMinHeartbeat < legalHeartbeat) {
|
||||
mPingMinHeartbeat = legalHeartbeat;
|
||||
}
|
||||
if (mPingForceHeartbeat < legalHeartbeat) {
|
||||
mPingForceHeartbeat = legalHeartbeat;
|
||||
}
|
||||
// If our minimum is now greater than the max, bring them together
|
||||
if (mPingMinHeartbeat > mPingMaxHeartbeat) {
|
||||
mPingMaxHeartbeat = legalHeartbeat;
|
||||
}
|
||||
} else if (legalHeartbeat < mPingHeartbeat) {
|
||||
// The legal heartbeat is lower than the ping heartbeat; therefore, our maximum was
|
||||
// too high. We respond by lowering the maximum to the argument value
|
||||
mPingMaxHeartbeat = legalHeartbeat;
|
||||
// If our maximum is now less than the minimum, bring them together
|
||||
if (mPingMaxHeartbeat < mPingMinHeartbeat) {
|
||||
mPingMinHeartbeat = legalHeartbeat;
|
||||
}
|
||||
}
|
||||
// Set current heartbeat to the legal heartbeat
|
||||
mPingHeartbeat = legalHeartbeat;
|
||||
// Allow the heartbeat logic to run
|
||||
mPingHeartbeatDropped = false;
|
||||
}
|
||||
|
||||
private void pushFallback(long mailboxId) {
|
||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
|
||||
if (mailbox == null) {
|
||||
@ -1593,7 +1638,8 @@ public class EasSyncService extends AbstractSyncService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void runPingLoop() throws IOException, StaleFolderListException {
|
||||
private void runPingLoop() throws IOException, StaleFolderListException,
|
||||
IllegalHeartbeatException {
|
||||
int pingHeartbeat = mPingHeartbeat;
|
||||
userLog("runPingLoop");
|
||||
// Do push for all sync services here
|
||||
@ -1693,7 +1739,7 @@ public class EasSyncService extends AbstractSyncService {
|
||||
userLog("Forcing ping after waiting for all boxes to be ready");
|
||||
}
|
||||
HttpResponse res =
|
||||
sendPing(s.toByteArray(), forcePing ? PING_FORCE_HEARTBEAT : pingHeartbeat);
|
||||
sendPing(s.toByteArray(), forcePing ? mPingForceHeartbeat : pingHeartbeat);
|
||||
|
||||
int code = res.getStatusLine().getStatusCode();
|
||||
userLog("Ping response: ", code);
|
||||
@ -1719,11 +1765,11 @@ public class EasSyncService extends AbstractSyncService {
|
||||
mPingHighWaterMark = pingHeartbeat;
|
||||
userLog("Setting high water mark at: ", mPingHighWaterMark);
|
||||
}
|
||||
if ((pingHeartbeat < PING_MAX_HEARTBEAT) &&
|
||||
if ((pingHeartbeat < mPingMaxHeartbeat) &&
|
||||
!mPingHeartbeatDropped) {
|
||||
pingHeartbeat += PING_HEARTBEAT_INCREMENT;
|
||||
if (pingHeartbeat > PING_MAX_HEARTBEAT) {
|
||||
pingHeartbeat = PING_MAX_HEARTBEAT;
|
||||
if (pingHeartbeat > mPingMaxHeartbeat) {
|
||||
pingHeartbeat = mPingMaxHeartbeat;
|
||||
}
|
||||
userLog("Increasing ping heartbeat to ", pingHeartbeat, "s");
|
||||
}
|
||||
@ -1748,12 +1794,12 @@ public class EasSyncService extends AbstractSyncService {
|
||||
// ping.
|
||||
} else if (mPostAborted || isLikelyNatFailure(message)) {
|
||||
long pingLength = SystemClock.elapsedRealtime() - pingTime;
|
||||
if ((pingHeartbeat > PING_MIN_HEARTBEAT) &&
|
||||
if ((pingHeartbeat > mPingMinHeartbeat) &&
|
||||
(pingHeartbeat > mPingHighWaterMark)) {
|
||||
pingHeartbeat -= PING_HEARTBEAT_INCREMENT;
|
||||
mPingHeartbeatDropped = true;
|
||||
if (pingHeartbeat < PING_MIN_HEARTBEAT) {
|
||||
pingHeartbeat = PING_MIN_HEARTBEAT;
|
||||
if (pingHeartbeat < mPingMinHeartbeat) {
|
||||
pingHeartbeat = mPingMinHeartbeat;
|
||||
}
|
||||
userLog("Decreased ping heartbeat to ", pingHeartbeat, "s");
|
||||
} else if (mPostAborted) {
|
||||
@ -1823,7 +1869,7 @@ public class EasSyncService extends AbstractSyncService {
|
||||
|
||||
private int parsePingResult(InputStream is, ContentResolver cr,
|
||||
HashMap<String, Integer> errorMap)
|
||||
throws IOException, StaleFolderListException {
|
||||
throws IOException, StaleFolderListException, IllegalHeartbeatException {
|
||||
PingParser pp = new PingParser(is, this);
|
||||
if (pp.parse()) {
|
||||
// True indicates some mailboxes need syncing...
|
||||
|
27
src/com/android/exchange/IllegalHeartbeatException.java
Normal file
27
src/com/android/exchange/IllegalHeartbeatException.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Licensed to The Android Open Source Project.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.exchange;
|
||||
|
||||
public class IllegalHeartbeatException extends EasException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public final int mLegalHeartbeat;
|
||||
|
||||
public IllegalHeartbeatException(int legalHeartbeat) {
|
||||
mLegalHeartbeat = legalHeartbeat;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
package com.android.exchange.adapter;
|
||||
|
||||
import com.android.exchange.EasSyncService;
|
||||
import com.android.exchange.IllegalHeartbeatException;
|
||||
import com.android.exchange.StaleFolderListException;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -62,7 +63,7 @@ public class PingParser extends Parser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean parse() throws IOException, StaleFolderListException {
|
||||
public boolean parse() throws IOException, StaleFolderListException, IllegalHeartbeatException {
|
||||
boolean res = false;
|
||||
if (nextTag(START_DOCUMENT) != Tags.PING_PING) {
|
||||
throw new IOException();
|
||||
@ -77,9 +78,15 @@ public class PingParser extends Parser {
|
||||
} else if (status == 7 || status == 4) {
|
||||
// Status of 7 or 4 indicate a stale folder list
|
||||
throw new StaleFolderListException();
|
||||
} else if (status == 5) {
|
||||
// Status 5 means our heartbeat is beyond allowable limits
|
||||
// In this case, there will be a heartbeat interval set
|
||||
}
|
||||
} else if (tag == Tags.PING_FOLDERS) {
|
||||
parsePingFolders(syncList);
|
||||
} else if (tag == Tags.PING_HEARTBEAT_INTERVAL) {
|
||||
// Throw an exception, saving away the legal heartbeat interval specified
|
||||
throw new IllegalHeartbeatException(getValueInt());
|
||||
} else {
|
||||
skipTag();
|
||||
}
|
||||
|
@ -23,7 +23,11 @@ import android.test.AndroidTestCase;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class EasSyncServiceTests extends AndroidTestCase {
|
||||
/**
|
||||
* You can run this entire test case with:
|
||||
* runtest -c com.android.exchange.EasSyncServiceTests email
|
||||
*/
|
||||
public class EasSyncServiceTests extends AndroidTestCase {
|
||||
Context mMockContext;
|
||||
|
||||
@Override
|
||||
@ -73,4 +77,46 @@ public class EasSyncServiceTests extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testResetHeartbeats() {
|
||||
EasSyncService svc = new EasSyncService();
|
||||
// Test case in which the minimum and force heartbeats need to come up
|
||||
svc.mPingMaxHeartbeat = 1000;
|
||||
svc.mPingMinHeartbeat = 200;
|
||||
svc.mPingHeartbeat = 300;
|
||||
svc.mPingForceHeartbeat = 100;
|
||||
svc.mPingHeartbeatDropped = true;
|
||||
svc.resetHeartbeats(400);
|
||||
assertEquals(400, svc.mPingMinHeartbeat);
|
||||
assertEquals(1000, svc.mPingMaxHeartbeat);
|
||||
assertEquals(400, svc.mPingHeartbeat);
|
||||
assertEquals(400, svc.mPingForceHeartbeat);
|
||||
assertFalse(svc.mPingHeartbeatDropped);
|
||||
|
||||
// Test case in which the force heartbeat needs to come up
|
||||
svc.mPingMaxHeartbeat = 1000;
|
||||
svc.mPingMinHeartbeat = 200;
|
||||
svc.mPingHeartbeat = 100;
|
||||
svc.mPingForceHeartbeat = 100;
|
||||
svc.mPingHeartbeatDropped = true;
|
||||
svc.resetHeartbeats(150);
|
||||
assertEquals(200, svc.mPingMinHeartbeat);
|
||||
assertEquals(1000, svc.mPingMaxHeartbeat);
|
||||
assertEquals(150, svc.mPingHeartbeat);
|
||||
assertEquals(150, svc.mPingForceHeartbeat);
|
||||
assertFalse(svc.mPingHeartbeatDropped);
|
||||
|
||||
// Test case in which the maximum needs to come down
|
||||
svc.mPingMaxHeartbeat = 1000;
|
||||
svc.mPingMinHeartbeat = 200;
|
||||
svc.mPingHeartbeat = 800;
|
||||
svc.mPingForceHeartbeat = 100;
|
||||
svc.mPingHeartbeatDropped = true;
|
||||
svc.resetHeartbeats(600);
|
||||
assertEquals(200, svc.mPingMinHeartbeat);
|
||||
assertEquals(600, svc.mPingMaxHeartbeat);
|
||||
assertEquals(600, svc.mPingHeartbeat);
|
||||
assertEquals(100, svc.mPingForceHeartbeat);
|
||||
assertFalse(svc.mPingHeartbeatDropped);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user