25b5f1c65f7f8fd01e806f2ff066e8447b07c727
[pub/Android/ownCloud.git] / src / com / owncloud / android / files / services / FileObserverService.java
1 package com.owncloud.android.files.services;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import com.owncloud.android.AccountUtils;
7 import com.owncloud.android.datamodel.FileDataStorageManager;
8 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
9 import com.owncloud.android.files.OwnCloudFileObserver;
10
11 import android.accounts.Account;
12 import android.accounts.AccountManager;
13 import android.app.Service;
14 import android.content.BroadcastReceiver;
15 import android.content.Context;
16 import android.content.Intent;
17 import android.content.IntentFilter;
18 import android.database.Cursor;
19 import android.os.Binder;
20 import android.os.IBinder;
21 import android.util.Log;
22
23 public class FileObserverService extends Service {
24
25 public final static String KEY_FILE_CMD = "KEY_FILE_CMD";
26 public final static String KEY_CMD_ARG = "KEY_CMD_ARG";
27
28 public final static int CMD_INIT_OBSERVED_LIST = 1;
29 public final static int CMD_ADD_OBSERVED_FILE = 2;
30 public final static int CMD_DEL_OBSERVED_FILE = 3;
31 public final static int CMD_ADD_DOWNLOADING_FILE = 4;
32
33 private static String TAG = "FileObserverService";
34 private static List<OwnCloudFileObserver> mObservers;
35 private static List<DownloadCompletedReceiver> mDownloadReceivers;
36 private static Object mReceiverListLock = new Object();
37 private IBinder mBinder = new LocalBinder();
38
39 public class LocalBinder extends Binder {
40 FileObserverService getService() {
41 return FileObserverService.this;
42 }
43 }
44
45 @Override
46 public IBinder onBind(Intent intent) {
47 return mBinder;
48 }
49
50 @Override
51 public int onStartCommand(Intent intent, int flags, int startId) {
52 // this occurs when system tries to restart
53 // service, so we need to reinitialize observers
54 if (intent == null) {
55 initializeObservedList();
56 return Service.START_STICKY;
57 }
58
59 if (!intent.hasExtra(KEY_FILE_CMD)) {
60 Log.e(TAG, "No KEY_FILE_CMD argument given");
61 return Service.START_STICKY;
62 }
63
64 switch (intent.getIntExtra(KEY_FILE_CMD, -1)) {
65 case CMD_INIT_OBSERVED_LIST:
66 initializeObservedList();
67 break;
68 case CMD_ADD_OBSERVED_FILE:
69 addObservedFile(intent.getStringExtra(KEY_CMD_ARG));
70 break;
71 case CMD_DEL_OBSERVED_FILE:
72 removeObservedFile(intent.getStringExtra(KEY_CMD_ARG));
73 break;
74 case CMD_ADD_DOWNLOADING_FILE:
75 addDownloadingFile(intent.getStringExtra(KEY_CMD_ARG));
76 break;
77 default:
78 Log.wtf(TAG, "Incorrect key given");
79 }
80
81 return Service.START_STICKY;
82 }
83
84 private void initializeObservedList() {
85 if (mObservers != null) return; // nothing to do here
86 mObservers = new ArrayList<OwnCloudFileObserver>();
87 mDownloadReceivers = new ArrayList<DownloadCompletedReceiver>();
88 Cursor c = getContentResolver().query(
89 ProviderTableMeta.CONTENT_URI,
90 null,
91 ProviderTableMeta.FILE_KEEP_IN_SYNC + " = ?",
92 new String[] {String.valueOf(1)},
93 null);
94 if (!c.moveToFirst()) return;
95 AccountManager acm = AccountManager.get(this);
96 Account[] accounts = acm.getAccounts();
97 do {
98 Account account = null;
99 for (Account a : accounts)
100 if (a.name.equals(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ACCOUNT_OWNER)))) {
101 account = a;
102 break;
103 }
104
105 if (account == null) continue;
106 FileDataStorageManager storage =
107 new FileDataStorageManager(account, getContentResolver());
108 if (!storage.fileExists(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))))
109 continue;
110
111 String path = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH));
112 OwnCloudFileObserver observer =
113 new OwnCloudFileObserver(path, OwnCloudFileObserver.CHANGES_ONLY);
114 observer.setContext(getApplicationContext());
115 observer.setAccount(account);
116 observer.setStorageManager(storage);
117 observer.setOCFile(storage.getFileByPath(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))));
118 observer.startWatching();
119 mObservers.add(observer);
120 Log.d(TAG, "Started watching file " + path);
121
122 } while (c.moveToNext());
123 c.close();
124 }
125
126 private void addObservedFile(String path) {
127 if (path == null) return;
128 if (mObservers == null) {
129 // this is very rare case when service was killed by system
130 // and observers list was deleted in that procedure
131 initializeObservedList();
132 }
133 boolean duplicate = false;
134 OwnCloudFileObserver observer = null;
135 for (int i = 0; i < mObservers.size(); ++i) {
136 observer = mObservers.get(i);
137 if (observer.getPath().equals(path))
138 duplicate = true;
139 observer.setContext(getBaseContext());
140 }
141 if (duplicate) return;
142 observer = new OwnCloudFileObserver(path, OwnCloudFileObserver.CHANGES_ONLY);
143 observer.setContext(getBaseContext());
144 Account account = AccountUtils.getCurrentOwnCloudAccount(getBaseContext());
145 observer.setAccount(account);
146 FileDataStorageManager storage =
147 new FileDataStorageManager(account, getContentResolver());
148 observer.setStorageManager(storage);
149 observer.setOCFile(storage.getFileByLocalPath(path));
150
151 DownloadCompletedReceiver receiver = new DownloadCompletedReceiver(path, observer);
152 registerReceiver(receiver, new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE));
153
154 mObservers.add(observer);
155 Log.d(TAG, "Observer added for path " + path);
156 }
157
158 private void removeObservedFile(String path) {
159 if (path == null) return;
160 if (mObservers == null) {
161 initializeObservedList();
162 return;
163 }
164 for (int i = 0; i < mObservers.size(); ++i) {
165 OwnCloudFileObserver observer = mObservers.get(i);
166 if (observer.getPath().equals(path)) {
167 observer.stopWatching();
168 mObservers.remove(i);
169 break;
170 }
171 }
172 Log.d(TAG, "Stopped watching " + path);
173 }
174
175 private void addDownloadingFile(String remotePath) {
176 OwnCloudFileObserver observer = null;
177 for (OwnCloudFileObserver o : mObservers) {
178 if (o.getRemotePath().equals(remotePath)) {
179 observer = o;
180 break;
181 }
182 }
183 if (observer == null) {
184 Log.e(TAG, "Couldn't find observer for remote file " + remotePath);
185 return;
186 }
187 observer.stopWatching();
188 DownloadCompletedReceiver dcr = new DownloadCompletedReceiver(observer.getPath(), observer);
189 registerReceiver(dcr, new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE));
190 }
191
192
193 private static void addReceiverToList(DownloadCompletedReceiver r) {
194 synchronized(mReceiverListLock) {
195 mDownloadReceivers.add(r);
196 }
197 }
198
199 private static void removeReceiverFromList(DownloadCompletedReceiver r) {
200 synchronized(mReceiverListLock) {
201 mDownloadReceivers.remove(r);
202 }
203 }
204
205 private class DownloadCompletedReceiver extends BroadcastReceiver {
206 String mPath;
207 OwnCloudFileObserver mObserver;
208
209 public DownloadCompletedReceiver(String path, OwnCloudFileObserver observer) {
210 mPath = path;
211 mObserver = observer;
212 addReceiverToList(this);
213 }
214
215 @Override
216 public void onReceive(Context context, Intent intent) {
217 if (mPath.equals(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH))) {
218 context.unregisterReceiver(this);
219 removeReceiverFromList(this);
220 mObserver.startWatching();
221 Log.d(TAG, "Started watching " + mPath);
222 return;
223 }
224 }
225
226 @Override
227 public boolean equals(Object o) {
228 if (o instanceof DownloadCompletedReceiver)
229 return mPath.equals(((DownloadCompletedReceiver)o).mPath);
230 return super.equals(o);
231 }
232 }
233 }