mobile/android/base/fxa/sync/FxAccountSyncStatusHelper.java

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:9ba8af38a3aa
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 package org.mozilla.gecko.fxa.sync;
6
7 import java.util.Map;
8 import java.util.Map.Entry;
9 import java.util.WeakHashMap;
10
11 import org.mozilla.gecko.fxa.FirefoxAccounts;
12 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
13
14 import android.content.ContentResolver;
15 import android.content.SyncStatusObserver;
16
17 /**
18 * Abstract away some details of Android's SyncStatusObserver.
19 * <p>
20 * Provides a simplified sync started/sync finished delegate.
21 */
22 public class FxAccountSyncStatusHelper implements SyncStatusObserver {
23 @SuppressWarnings("unused")
24 private static final String LOG_TAG = FxAccountSyncStatusHelper.class.getSimpleName();
25
26 protected static FxAccountSyncStatusHelper sInstance = null;
27
28 public synchronized static FxAccountSyncStatusHelper getInstance() {
29 if (sInstance == null) {
30 sInstance = new FxAccountSyncStatusHelper();
31 }
32 return sInstance;
33 }
34
35 // Used to unregister this as a listener.
36 protected Object handle = null;
37
38 // Maps delegates to whether their underlying Android account was syncing the
39 // last time we observed a status change.
40 protected Map<FirefoxAccounts.SyncStatusListener, Boolean> delegates = new WeakHashMap<FirefoxAccounts.SyncStatusListener, Boolean>();
41
42 @Override
43 public synchronized void onStatusChanged(int which) {
44 for (Entry<FirefoxAccounts.SyncStatusListener, Boolean> entry : delegates.entrySet()) {
45 final FirefoxAccounts.SyncStatusListener delegate = entry.getKey();
46 final AndroidFxAccount fxAccount = new AndroidFxAccount(delegate.getContext(), delegate.getAccount());
47 final boolean active = fxAccount.isCurrentlySyncing();
48 // Remember for later.
49 boolean wasActiveLastTime = entry.getValue();
50 // It's okay to update the value of an entry while iterating the entrySet.
51 entry.setValue(active);
52
53 if (active && !wasActiveLastTime) {
54 // We've started a sync.
55 delegate.onSyncStarted();
56 }
57 if (!active && wasActiveLastTime) {
58 // We've finished a sync.
59 delegate.onSyncFinished();
60 }
61 }
62 }
63
64 protected void addListener() {
65 final int mask = ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
66 if (this.handle != null) {
67 throw new IllegalStateException("Already registered this as an observer?");
68 }
69 this.handle = ContentResolver.addStatusChangeListener(mask, this);
70 }
71
72 protected void removeListener() {
73 Object handle = this.handle;
74 this.handle = null;
75 if (handle != null) {
76 ContentResolver.removeStatusChangeListener(handle);
77 }
78 }
79
80 public synchronized void startObserving(FirefoxAccounts.SyncStatusListener delegate) {
81 if (delegate == null) {
82 throw new IllegalArgumentException("delegate must not be null");
83 }
84 if (delegates.containsKey(delegate)) {
85 return;
86 }
87 // If we are the first delegate to the party, start listening.
88 if (delegates.isEmpty()) {
89 addListener();
90 }
91 delegates.put(delegate, Boolean.FALSE);
92 }
93
94 public synchronized void stopObserving(FirefoxAccounts.SyncStatusListener delegate) {
95 delegates.remove(delegate);
96 // If we are the last delegate leaving the party, stop listening.
97 if (delegates.isEmpty()) {
98 removeListener();
99 }
100 }
101 }

mercurial