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. Always null.
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        this(name);
64    }
65
66    /** @hide */
67    WebSyncManager(String name) {
68        mThreadName = name;
69        mSyncThread = new Thread(this);
70        mSyncThread.setName(mThreadName);
71        mSyncThread.start();
72    }
73
74    protected Object clone() throws CloneNotSupportedException {
75        throw new CloneNotSupportedException("doesn't implement Cloneable");
76    }
77
78    public void run() {
79        // prepare Looper for sync handler
80        Looper.prepare();
81        mHandler = new SyncHandler();
82        onSyncInit();
83        // lower the priority after onSyncInit() is done
84        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
85
86        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
87        mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
88
89        Looper.loop();
90    }
91
92    /**
93     * sync() forces sync manager to sync now
94     */
95    public void sync() {
96        if (DebugFlags.WEB_SYNC_MANAGER) {
97            Log.v(LOGTAG, "*** WebSyncManager sync ***");
98        }
99        if (mHandler == null) {
100            return;
101        }
102        mHandler.removeMessages(SYNC_MESSAGE);
103        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
104        mHandler.sendMessageDelayed(msg, SYNC_NOW_INTERVAL);
105    }
106
107    /**
108     * resetSync() resets sync manager's timer
109     */
110    public void resetSync() {
111        if (DebugFlags.WEB_SYNC_MANAGER) {
112            Log.v(LOGTAG, "*** WebSyncManager resetSync ***");
113        }
114        if (mHandler == null) {
115            return;
116        }
117        mHandler.removeMessages(SYNC_MESSAGE);
118        Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
119        mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
120    }
121
122    /**
123     * startSync() requests sync manager to start sync
124     */
125    public void startSync() {
126        if (DebugFlags.WEB_SYNC_MANAGER) {
127            Log.v(LOGTAG, "***  WebSyncManager startSync ***, Ref count:" +
128                    mStartSyncRefCount);
129        }
130        if (mHandler == null) {
131            return;
132        }
133        if (++mStartSyncRefCount == 1) {
134            Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
135            mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
136        }
137    }
138
139    /**
140     * stopSync() requests sync manager to stop sync. remove any SYNC_MESSAGE in
141     * the queue to break the sync loop
142     */
143    public void stopSync() {
144        if (DebugFlags.WEB_SYNC_MANAGER) {
145            Log.v(LOGTAG, "*** WebSyncManager stopSync ***, Ref count:" +
146                    mStartSyncRefCount);
147        }
148        if (mHandler == null) {
149            return;
150        }
151        if (--mStartSyncRefCount == 0) {
152            mHandler.removeMessages(SYNC_MESSAGE);
153        }
154    }
155
156    protected void onSyncInit() {
157    }
158
159    abstract void syncFromRamToFlash();
160}
161