1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.content; 18 19import android.accounts.Account; 20import android.os.Bundle; 21import android.os.SystemClock; 22 23/** 24 * Value type that represents a sync operation. 25 * @hide 26 */ 27public class SyncOperation implements Comparable { 28 public final Account account; 29 public final int userId; 30 public int syncSource; 31 public String authority; 32 public final boolean allowParallelSyncs; 33 public Bundle extras; 34 public final String key; 35 public long earliestRunTime; 36 public boolean expedited; 37 public SyncStorageEngine.PendingOperation pendingOperation; 38 public Long backoff; 39 public long delayUntil; 40 public long effectiveRunTime; 41 42 public SyncOperation(Account account, int userId, int source, String authority, Bundle extras, 43 long delayInMs, long backoff, long delayUntil, boolean allowParallelSyncs) { 44 this.account = account; 45 this.userId = userId; 46 this.syncSource = source; 47 this.authority = authority; 48 this.allowParallelSyncs = allowParallelSyncs; 49 this.extras = new Bundle(extras); 50 removeFalseExtra(ContentResolver.SYNC_EXTRAS_UPLOAD); 51 removeFalseExtra(ContentResolver.SYNC_EXTRAS_MANUAL); 52 removeFalseExtra(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS); 53 removeFalseExtra(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF); 54 removeFalseExtra(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY); 55 removeFalseExtra(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS); 56 removeFalseExtra(ContentResolver.SYNC_EXTRAS_EXPEDITED); 57 removeFalseExtra(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS); 58 this.delayUntil = delayUntil; 59 this.backoff = backoff; 60 final long now = SystemClock.elapsedRealtime(); 61 if (delayInMs < 0) { 62 this.expedited = true; 63 this.earliestRunTime = now; 64 } else { 65 this.expedited = false; 66 this.earliestRunTime = now + delayInMs; 67 } 68 updateEffectiveRunTime(); 69 this.key = toKey(); 70 } 71 72 private void removeFalseExtra(String extraName) { 73 if (!extras.getBoolean(extraName, false)) { 74 extras.remove(extraName); 75 } 76 } 77 78 SyncOperation(SyncOperation other) { 79 this.account = other.account; 80 this.userId = other.userId; 81 this.syncSource = other.syncSource; 82 this.authority = other.authority; 83 this.extras = new Bundle(other.extras); 84 this.expedited = other.expedited; 85 this.earliestRunTime = SystemClock.elapsedRealtime(); 86 this.backoff = other.backoff; 87 this.delayUntil = other.delayUntil; 88 this.allowParallelSyncs = other.allowParallelSyncs; 89 this.updateEffectiveRunTime(); 90 this.key = toKey(); 91 } 92 93 public String toString() { 94 return dump(true); 95 } 96 97 public String dump(boolean useOneLine) { 98 StringBuilder sb = new StringBuilder() 99 .append(account.name) 100 .append(" u") 101 .append(userId).append(" (") 102 .append(account.type) 103 .append(")") 104 .append(", ") 105 .append(authority) 106 .append(", ") 107 .append(SyncStorageEngine.SOURCES[syncSource]) 108 .append(", earliestRunTime ") 109 .append(earliestRunTime); 110 if (expedited) { 111 sb.append(", EXPEDITED"); 112 } 113 if (!useOneLine && !extras.keySet().isEmpty()) { 114 sb.append("\n "); 115 extrasToStringBuilder(extras, sb); 116 } 117 return sb.toString(); 118 } 119 120 public boolean isInitialization() { 121 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false); 122 } 123 124 public boolean isExpedited() { 125 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false); 126 } 127 128 public boolean ignoreBackoff() { 129 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false); 130 } 131 132 private String toKey() { 133 StringBuilder sb = new StringBuilder(); 134 sb.append("authority: ").append(authority); 135 sb.append(" account {name=" + account.name + ", user=" + userId + ", type=" + account.type 136 + "}"); 137 sb.append(" extras: "); 138 extrasToStringBuilder(extras, sb); 139 return sb.toString(); 140 } 141 142 public static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) { 143 sb.append("["); 144 for (String key : bundle.keySet()) { 145 sb.append(key).append("=").append(bundle.get(key)).append(" "); 146 } 147 sb.append("]"); 148 } 149 150 public void updateEffectiveRunTime() { 151 effectiveRunTime = ignoreBackoff() 152 ? earliestRunTime 153 : Math.max( 154 Math.max(earliestRunTime, delayUntil), 155 backoff); 156 } 157 158 public int compareTo(Object o) { 159 SyncOperation other = (SyncOperation)o; 160 161 if (expedited != other.expedited) { 162 return expedited ? -1 : 1; 163 } 164 165 if (effectiveRunTime == other.effectiveRunTime) { 166 return 0; 167 } 168 169 return effectiveRunTime < other.effectiveRunTime ? -1 : 1; 170 } 171} 172