OLD | NEW |
| (Empty) |
1 /* | |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
3 * Copyright (C) 2006-present eyeo GmbH | |
4 * | |
5 * Adblock Plus is free software: you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 3 as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | |
16 */ | |
17 | |
18 package org.adblockplus.sbrowser.contentblocker.engine; | |
19 | |
20 import java.util.concurrent.LinkedBlockingQueue; | |
21 | |
22 import android.app.Service; | |
23 import android.content.Context; | |
24 import android.content.Intent; | |
25 import android.os.IBinder; | |
26 import android.util.Log; | |
27 | |
28 public final class EngineService extends Service | |
29 { | |
30 private static final String TAG = EngineService.class.getSimpleName(); | |
31 | |
32 private volatile Engine engine = null; | |
33 private volatile boolean isInitialized = false; | |
34 private Throwable failureCause = null; | |
35 private static final LinkedBlockingQueue<EngineCreatedCallbackWrapper> ON_CREA
TED_CALLBACKS = | |
36 new LinkedBlockingQueue<>(); | |
37 | |
38 @Override | |
39 public int onStartCommand(Intent intent, int flags, int startId) | |
40 { | |
41 return Service.START_NOT_STICKY; | |
42 } | |
43 | |
44 /** | |
45 * The callback gets executed on the UI thread. | |
46 * | |
47 * @param context | |
48 * @param callback | |
49 */ | |
50 public static void startService(final Context context, final OnEngineCreatedCa
llback callback) | |
51 { | |
52 startService(context, callback, true); | |
53 } | |
54 | |
55 /** | |
56 * | |
57 * @param context | |
58 * @param callback | |
59 * @param runOnUiThread | |
60 * {@code true} if the callback should be executed on the UI thread | |
61 */ | |
62 public static void startService(final Context context, final OnEngineCreatedCa
llback callback, | |
63 final boolean runOnUiThread) | |
64 { | |
65 context.startService(new Intent(context, EngineService.class)); | |
66 ON_CREATED_CALLBACKS.offer(new EngineCreatedCallbackWrapper(callback, runOnU
iThread)); | |
67 } | |
68 | |
69 @Override | |
70 public void onCreate() | |
71 { | |
72 super.onCreate(); | |
73 startDaemonThread(new Initializer(this)); | |
74 startDaemonThread(new CreationNotifier(this)); | |
75 } | |
76 | |
77 @Override | |
78 public IBinder onBind(Intent intent) | |
79 { | |
80 return null; | |
81 } | |
82 | |
83 private static void startDaemonThread(final Runnable runnable) | |
84 { | |
85 final Thread t = new Thread(runnable); | |
86 t.setDaemon(true); | |
87 t.start(); | |
88 } | |
89 | |
90 private static class Initializer implements Runnable | |
91 { | |
92 private final EngineService service; | |
93 | |
94 public Initializer(final EngineService service) | |
95 { | |
96 this.service = service; | |
97 } | |
98 | |
99 @Override | |
100 public void run() | |
101 { | |
102 try | |
103 { | |
104 this.service.engine = Engine.create(this.service.getApplicationContext()
); | |
105 } | |
106 catch (Throwable t) | |
107 { | |
108 Log.e(TAG, "Initialization failed: " + t.getMessage(), t); | |
109 this.service.failureCause = t; | |
110 } | |
111 finally | |
112 { | |
113 this.service.isInitialized = true; | |
114 } | |
115 } | |
116 } | |
117 | |
118 private static class CreationNotifier implements Runnable | |
119 { | |
120 private static final String TAG = CreationNotifier.class.getSimpleName(); | |
121 private final EngineService service; | |
122 | |
123 public CreationNotifier(final EngineService service) | |
124 { | |
125 this.service = service; | |
126 } | |
127 | |
128 @Override | |
129 public void run() | |
130 { | |
131 try | |
132 { | |
133 while (!this.service.isInitialized) | |
134 { | |
135 Thread.sleep(250); | |
136 } | |
137 | |
138 for (;;) | |
139 { | |
140 final EngineCreatedCallbackWrapper wrapper = EngineService.ON_CREATED_
CALLBACKS.take(); | |
141 if (wrapper != null) | |
142 { | |
143 if (wrapper.runOnUiThread) | |
144 { | |
145 Engine.runOnUiThread(new Runnable() | |
146 { | |
147 private final EngineService service = CreationNotifier.this.serv
ice; | |
148 | |
149 @Override | |
150 public void run() | |
151 { | |
152 wrapper.callback.onEngineCreated(this.service.engine, | |
153 this.service.failureCause == null); | |
154 } | |
155 }); | |
156 } | |
157 else | |
158 { | |
159 wrapper.callback.onEngineCreated(this.service.engine, | |
160 this.service.failureCause == null); | |
161 } | |
162 } | |
163 } | |
164 } | |
165 catch (final Throwable t) | |
166 { | |
167 Log.e(TAG, "Notifier died: " + t.getMessage(), t); | |
168 } | |
169 } | |
170 } | |
171 | |
172 public interface OnEngineCreatedCallback | |
173 { | |
174 void onEngineCreated(Engine engine, boolean success); | |
175 } | |
176 | |
177 private static class EngineCreatedCallbackWrapper | |
178 { | |
179 final OnEngineCreatedCallback callback; | |
180 final boolean runOnUiThread; | |
181 | |
182 public EngineCreatedCallbackWrapper(final OnEngineCreatedCallback callback, | |
183 final boolean runOnUiThread) | |
184 { | |
185 this.callback = callback; | |
186 this.runOnUiThread = runOnUiThread; | |
187 } | |
188 } | |
189 } | |
OLD | NEW |