1/*
2 * Copyright (C) 2007 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.webkit;
18
19import android.content.Context;
20import android.os.Handler;
21import android.os.Looper;
22import android.os.Message;
23import android.os.Process;
24import android.util.Log;
25
26abstract class WebSyncManager implements Runnable {
27    // message code for sync message
28    private static final int SYNC_MESSAGE = 101;
29    // time delay in millisec for a sync (now) message
30    private static int SYNC_NOW_INTERVAL = 100; // 100 millisec
31    // time delay in millisec for a sync (later) message
32    private static int SYNC_LATER_INTERVAL = 5 * 60 * 1000; // 5 minutes
33    // thread for syncing
34    private Thread mSyncThread;
35    // Name of thread
36    private String mThreadName;
37    // handler of the sync thread
38    protected Handler mHandler;
39    // database for the persistent storage
40    protected WebViewDatabase mDataBase;
41    // Ref count for calls to start/stop sync
42    private int mStartSyncRefCount;
43    // log tag
44    protected static final String LOGTAG = "websync";
45
46    private class SyncHandler extends Handler {
47        @Override
48        public void handleMessage(Message msg) {
49            if (msg.what == SYNC_MESSAGE) {
50                if (DebugFlags.WEB_SYNC_MANAGER) {
51                    Log.v(LOGTAG, "*** WebSyncManager sync ***");
52                }
53                syncFromRamToFlash();
54
55                // send a delayed message to request sync later
56                Message newmsg = obtainMessage(SYNC_MESSAGE);
57                sendMessageDelayed(newmsg, SYNC_LATER_INTERVAL);
58            }
59        }
60    }
61
62    protected WebSyncManager(Context context, String name) {
63        mThreadName = name;
64        if (context != null) {
65            mDataBase = WebViewDatabase.getInstance(context);
66            mSyncThread = new Thread(this);
67            mSyncThread.setName(mThreadName);
68            mSyncThread.start();
69        } else {
70            throw new IllegalStateException(
71                    "WebSyncManager can't be created without context");
72        }
73    }
74
75    protected Object clone() throws CloneNotSupportedException {
76        throw new CloneNotSupportedException("doesn't implement Cloneable");
77    }
78
79    public void run() {
80        // prepare Looper for sync handler
81        Looper.prepare();
82        mHandler = new SyncHandler();
83        onSyncInit();
84        // lower the priority after onSyncInit() is done
85       Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
86
87        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
88        mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
89
90        Looper.loop();
91    }
92
93    /**
94     * sync() forces sync manager to sync now
95     */
96    public void sync() {
97        if (DebugFlags.WEB_SYNC_MANAGER) {
98            Log.v(LOGTAG, "*** WebSyncManager sync ***");
99        }
100        if (mHandler == null) {
101            return;
102        }
103        mHandler.removeMessages(SYNC_MESSAGE);
104        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
105        mHandler.sendMessageDelayed(msg, SYNC_NOW_INTERVAL);
106    }
107
108    /**
109     * resetSync() resets sync manager's timer
110     */
111    public void resetSync() {
112        if (DebugFlags.WEB_SYNC_MANAGER) {
113            Log.v(LOGTAG, "*** WebSyncManager resetSync ***");
114        }
115        if (mHandler == null) {
116            return;
117        }
118        mHandler.removeMessages(SYNC_MESSAGE);
119        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
120        mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
121    }
122
123    /**
124     * startSync() requests sync manager to start sync
125     */
126    public void startSync() {
127        if (DebugFlags.WEB_SYNC_MANAGER) {
128            Log.v(LOGTAG, "***  WebSyncManager startSync ***, Ref count:" +
129                    mStartSyncRefCount);
130        }
131        if (mHandler == null) {
132            return;
133        }
134        if (++mStartSyncRefCount == 1) {
135            Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
136            mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
137        }
138    }
139
140    /**
141     * stopSync() requests sync manager to stop sync. remove any SYNC_MESSAGE in
142     * the queue to break the sync loop
143     */
144    public void stopSync() {
145        if (DebugFlags.WEB_SYNC_MANAGER) {
146            Log.v(LOGTAG, "*** WebSyncManager stopSync ***, Ref count:" +
147                    mStartSyncRefCount);
148        }
149        if (mHandler == null) {
150            return;
151        }
152        if (--mStartSyncRefCount == 0) {
153            mHandler.removeMessages(SYNC_MESSAGE);
154        }
155    }
156
157    protected void onSyncInit() {
158    }
159
160    abstract void syncFromRamToFlash();
161}
162