blob: e824d7e344e05cf68cb050d85621590fd9b4c56f [file] [log] [blame]
Romain Guy55a384c2009-08-12 10:58:02 -07001/*
2 * Copyright (C) 2009 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 com.android.wallpaper.grass;
18
Romain Guy55a384c2009-08-12 10:58:02 -070019import android.renderscript.Sampler;
20import static android.renderscript.ProgramFragment.EnvMode.*;
21import static android.renderscript.ProgramStore.DepthFunc.*;
22import static android.renderscript.ProgramStore.BlendSrcFunc;
23import static android.renderscript.ProgramStore.BlendDstFunc;
Romain Guy55a384c2009-08-12 10:58:02 -070024import android.renderscript.ProgramFragment;
25import android.renderscript.ProgramStore;
26import android.renderscript.Allocation;
27import android.renderscript.ProgramVertex;
28import static android.renderscript.Element.*;
29import static android.util.MathUtils.*;
30import android.renderscript.ScriptC;
31import android.renderscript.Type;
32import android.renderscript.Dimension;
Romain Guyb7d22522009-08-20 12:08:50 -070033import android.renderscript.Element;
34import android.renderscript.SimpleMesh;
35import android.renderscript.Primitive;
Romain Guy55a384c2009-08-12 10:58:02 -070036import static android.renderscript.Sampler.Value.*;
Romain Guya56ce012009-10-13 17:05:45 -070037import android.content.Context;
38import android.content.IntentFilter;
39import android.content.Intent;
40import android.content.BroadcastReceiver;
41import android.location.LocationManager;
42import android.location.LocationListener;
43import android.location.Location;
44import android.os.Bundle;
45import android.text.format.Time;
Romain Guy55a384c2009-08-12 10:58:02 -070046import com.android.wallpaper.R;
Romain Guy44da1782009-08-28 11:03:21 -070047import com.android.wallpaper.RenderScriptScene;
Romain Guy55a384c2009-08-12 10:58:02 -070048
49import java.util.TimeZone;
Romain Guya56ce012009-10-13 17:05:45 -070050import java.util.Calendar;
Romain Guy55a384c2009-08-12 10:58:02 -070051
Romain Guy44da1782009-08-28 11:03:21 -070052class GrassRS extends RenderScriptScene {
Romain Guya56ce012009-10-13 17:05:45 -070053 private static final int LOCATION_UPDATE_MIN_TIME = 60 * 60 * 1000; // 1 hour
54 private static final int LOCATION_UPDATE_MIN_DISTANCE = 150 * 1000; // 150 km
55
Romain Guyb7d22522009-08-20 12:08:50 -070056 private static final float TESSELATION = 0.5f;
Romain Guy55a384c2009-08-12 10:58:02 -070057 private static final int TEXTURES_COUNT = 5;
58
Romain Guya56ce012009-10-13 17:05:45 -070059 private static final int RSID_STATE = 0;
Romain Guy55a384c2009-08-12 10:58:02 -070060 private static final int RSID_BLADES = 1;
61 private static final int BLADES_COUNT = 200;
Romain Guyb7d22522009-08-20 12:08:50 -070062 private static final int BLADE_STRUCT_FIELDS_COUNT = 13;
Romain Guy55a384c2009-08-12 10:58:02 -070063 private static final int BLADE_STRUCT_ANGLE = 0;
64 private static final int BLADE_STRUCT_SIZE = 1;
65 private static final int BLADE_STRUCT_XPOS = 2;
66 private static final int BLADE_STRUCT_YPOS = 3;
67 private static final int BLADE_STRUCT_OFFSET = 4;
68 private static final int BLADE_STRUCT_SCALE = 5;
69 private static final int BLADE_STRUCT_LENGTHX = 6;
70 private static final int BLADE_STRUCT_LENGTHY = 7;
71 private static final int BLADE_STRUCT_HARDNESS = 8;
72 private static final int BLADE_STRUCT_H = 9;
73 private static final int BLADE_STRUCT_S = 10;
74 private static final int BLADE_STRUCT_B = 11;
Romain Guyb7d22522009-08-20 12:08:50 -070075 private static final int BLADE_STRUCT_TURBULENCEX = 12;
76
77 private static final int RSID_BLADES_BUFFER = 2;
Romain Guy55a384c2009-08-12 10:58:02 -070078
Romain Guyb7d22522009-08-20 12:08:50 -070079 @SuppressWarnings({ "FieldCanBeLocal" })
Romain Guy55a384c2009-08-12 10:58:02 -070080 private ProgramFragment mPfBackground;
Romain Guyb7d22522009-08-20 12:08:50 -070081 @SuppressWarnings({ "FieldCanBeLocal" })
Romain Guy55a384c2009-08-12 10:58:02 -070082 private ProgramStore mPfsBackground;
Romain Guyb7d22522009-08-20 12:08:50 -070083 @SuppressWarnings({ "FieldCanBeLocal" })
Romain Guy55a384c2009-08-12 10:58:02 -070084 private ProgramVertex mPvBackground;
Romain Guyff41eed2009-08-24 13:55:57 -070085 @SuppressWarnings({"FieldCanBeLocal"})
86 private Sampler mSampler;
87 @SuppressWarnings({"FieldCanBeLocal"})
88 private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
Romain Guy55a384c2009-08-12 10:58:02 -070089
Romain Guyb7d22522009-08-20 12:08:50 -070090 @SuppressWarnings({ "FieldCanBeLocal" })
Romain Guy55a384c2009-08-12 10:58:02 -070091 private Allocation[] mTextures;
92
Romain Guyb7d22522009-08-20 12:08:50 -070093 private Type mStateType;
Romain Guy55a384c2009-08-12 10:58:02 -070094 private Allocation mState;
Romain Guyb7d22522009-08-20 12:08:50 -070095
Romain Guy55a384c2009-08-12 10:58:02 -070096 private Allocation mBlades;
Romain Guyb7d22522009-08-20 12:08:50 -070097 private Allocation mBladesBuffer;
Romain Guyff41eed2009-08-24 13:55:57 -070098 @SuppressWarnings({"FieldCanBeLocal"})
99 private SimpleMesh mBladesMesh;
Romain Guyb7d22522009-08-20 12:08:50 -0700100
101 private int mTriangles;
Romain Guyf0bb9562009-10-07 12:25:24 -0700102 private float[] mBladesData;
Romain Guya56ce012009-10-13 17:05:45 -0700103 private final float[] mFloatData5 = new float[5];
Romain Guy55a384c2009-08-12 10:58:02 -0700104
Romain Guya56ce012009-10-13 17:05:45 -0700105 private WorldState mWorldState;
106
107 private final Context mContext;
108 private final LocationManager mLocationManager;
109
110 private LocationUpdater mLocationUpdater;
111 private GrassRS.TimezoneTracker mTimezoneTracker;
112
113 GrassRS(Context context, int width, int height) {
Romain Guy44da1782009-08-28 11:03:21 -0700114 super(width, height);
Romain Guya56ce012009-10-13 17:05:45 -0700115
116 mContext = context;
117 mLocationManager = (LocationManager)
118 context.getSystemService(Context.LOCATION_SERVICE);
119 }
120
121 @Override
122 public void start() {
123 super.start();
124
125 if (mTimezoneTracker == null) {
126 mTimezoneTracker = new TimezoneTracker();
127 IntentFilter filter = new IntentFilter();
128 filter.addAction(Intent.ACTION_TIME_CHANGED);
129 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
130
131 mContext.registerReceiver(mTimezoneTracker, filter);
132 }
133
134 if (mLocationUpdater == null) {
135 mLocationUpdater = new LocationUpdater();
136 mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
137 LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, mLocationUpdater);
138 }
139
140 updateLocation();
141 }
142
143 @Override
144 public void stop() {
145 super.stop();
146
147 if (mTimezoneTracker != null) {
148 mContext.unregisterReceiver(mTimezoneTracker);
149 mTimezoneTracker = null;
150 }
151
152 if (mLocationUpdater != null) {
153 mLocationManager.removeUpdates(mLocationUpdater);
154 mLocationUpdater = null;
155 }
Romain Guy55a384c2009-08-12 10:58:02 -0700156 }
157
Romain Guy44da1782009-08-28 11:03:21 -0700158 @Override
159 public void resize(int width, int height) {
160 super.resize(width, height);
Jason Sams575d5142009-09-27 17:51:22 -0700161
Romain Guy9e6f2342009-08-24 18:40:21 -0700162 mWorldState.width = width;
163 mWorldState.height = height;
164 mState.data(mWorldState);
165
Romain Guyf0bb9562009-10-07 12:25:24 -0700166 final float[] blades = mBladesData;
167 for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
168 updateBlade(blades, i);
169 }
170 mBlades.data(blades);
Romain Guy9e6f2342009-08-24 18:40:21 -0700171
Romain Guyf0bb9562009-10-07 12:25:24 -0700172 mPvOrthoAlloc.setupOrthoWindow(width, height);
Romain Guy9e6f2342009-08-24 18:40:21 -0700173 }
Romain Guy44da1782009-08-28 11:03:21 -0700174
175 @Override
176 protected ScriptC createScript() {
Romain Guy55a384c2009-08-12 10:58:02 -0700177 createProgramVertex();
178 createProgramFragmentStore();
179 createProgramFragment();
180 createScriptStructures();
181 loadTextures();
182
183 ScriptC.Builder sb = new ScriptC.Builder(mRS);
Romain Guyb7d22522009-08-20 12:08:50 -0700184 sb.setType(mStateType, "State", RSID_STATE);
Romain Guy55a384c2009-08-12 10:58:02 -0700185 sb.setScript(mResources, R.raw.grass);
186 sb.setRoot(true);
Romain Guyb7d22522009-08-20 12:08:50 -0700187
Romain Guy44da1782009-08-28 11:03:21 -0700188 ScriptC script = sb.create();
189 script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
190 script.setTimeZone(TimeZone.getDefault().getID());
Romain Guy55a384c2009-08-12 10:58:02 -0700191
Romain Guy44da1782009-08-28 11:03:21 -0700192 script.bindAllocation(mState, RSID_STATE);
193 script.bindAllocation(mBlades, RSID_BLADES);
194 script.bindAllocation(mBladesBuffer, RSID_BLADES_BUFFER);
Jason Sams575d5142009-09-27 17:51:22 -0700195
Romain Guy44da1782009-08-28 11:03:21 -0700196 return script;
Romain Guy55a384c2009-08-12 10:58:02 -0700197 }
198
199 private void createScriptStructures() {
Romain Guyb7d22522009-08-20 12:08:50 -0700200 createBlades();
201 createState();
Romain Guy55a384c2009-08-12 10:58:02 -0700202 }
203
Romain Guy44da1782009-08-28 11:03:21 -0700204 @Override
205 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
206 mWorldState.xOffset = xOffset;
207 mState.data(mWorldState);
208 }
209
Romain Guyb7d22522009-08-20 12:08:50 -0700210 static class WorldState {
Romain Guyb7d22522009-08-20 12:08:50 -0700211 public int bladesCount;
212 public int trianglesCount;
213 public int width;
214 public int height;
Romain Guy44da1782009-08-28 11:03:21 -0700215 public float xOffset;
Romain Guya56ce012009-10-13 17:05:45 -0700216 public float dawn;
217 public float morning;
218 public float afternoon;
219 public float dusk;
Romain Guyb7d22522009-08-20 12:08:50 -0700220 }
221
222 private void createState() {
Romain Guy9e6f2342009-08-24 18:40:21 -0700223 mWorldState = new WorldState();
224 mWorldState.width = mWidth;
225 mWorldState.height = mHeight;
226 mWorldState.bladesCount = BLADES_COUNT;
227 mWorldState.trianglesCount = mTriangles;
Romain Guyb7d22522009-08-20 12:08:50 -0700228
229 mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
230 mState = Allocation.createTyped(mRS, mStateType);
Romain Guy9e6f2342009-08-24 18:40:21 -0700231 mState.data(mWorldState);
Romain Guyb7d22522009-08-20 12:08:50 -0700232 }
233
234 private void createBlades() {
235 int triangles = 0;
236
Romain Guyf0bb9562009-10-07 12:25:24 -0700237 mBladesData = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
238
239 final float[] blades = mBladesData;
Romain Guyb7d22522009-08-20 12:08:50 -0700240 for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
241 triangles += createBlade(blades, i);
242 }
243
Jason Sams575d5142009-09-27 17:51:22 -0700244 mBlades = Allocation.createSized(mRS, USER_F32(mRS), blades.length);
Romain Guyb7d22522009-08-20 12:08:50 -0700245 mBlades.data(blades);
246
247 mTriangles = triangles;
248
249 createMesh(triangles);
250 }
251
252 private void createMesh(int triangles) {
253 Builder elementBuilder = new Builder(mRS);
254 elementBuilder.addUNorm8RGBA();
255 elementBuilder.addFloatXY();
256 elementBuilder.addFloatST();
257 final Element vertexElement = elementBuilder.create();
258
259 final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
260 final int vertexSlot = meshBuilder.addVertexType(vertexElement, triangles * 3);
261 meshBuilder.setPrimitive(Primitive.TRIANGLE);
Romain Guye04d27e2009-08-21 16:30:52 -0700262 mBladesMesh = meshBuilder.create();
263 mBladesMesh.setName("BladesMesh");
Romain Guyb7d22522009-08-20 12:08:50 -0700264
Romain Guye04d27e2009-08-21 16:30:52 -0700265 mBladesBuffer = mBladesMesh.createVertexAllocation(vertexSlot);
Romain Guyb7d22522009-08-20 12:08:50 -0700266 mBladesBuffer.setName("BladesBuffer");
Romain Guye04d27e2009-08-21 16:30:52 -0700267 mBladesMesh.bindVertexAllocation(mBladesBuffer, 0);
Romain Guyb7d22522009-08-20 12:08:50 -0700268
269 // Assign the texture coordinates of each triangle
270 final float[] floatData = mFloatData5;
271 final Allocation buffer = mBladesBuffer;
272
273 int bufferIndex = 0;
274 for (int i = 0; i < triangles; i += 2) {
275 floatData[3] = 0.0f;
276 floatData[4] = 1.0f;
277 buffer.subData1D(bufferIndex, 1, floatData);
278 bufferIndex++;
279
280 floatData[3] = 0.0f;
281 floatData[4] = 0.0f;
282 buffer.subData1D(bufferIndex, 1, floatData);
283 bufferIndex++;
284
285 floatData[3] = 1.0f;
286 floatData[4] = 0.0f;
287 buffer.subData1D(bufferIndex, 1, floatData);
288 bufferIndex++;
289
290 floatData[3] = 0.0f;
291 floatData[4] = 0.0f;
292 buffer.subData1D(bufferIndex, 1, floatData);
293 bufferIndex++;
294
295 floatData[3] = 1.0f;
296 floatData[4] = 1.0f;
297 buffer.subData1D(bufferIndex, 1, floatData);
298 bufferIndex++;
299
300 floatData[3] = 1.0f;
301 floatData[4] = 0.0f;
302 buffer.subData1D(bufferIndex, 1, floatData);
303 bufferIndex++;
304 }
305 }
306
Romain Guyf0bb9562009-10-07 12:25:24 -0700307 private void updateBlade(float[] blades, int index) {
308 final int xpos = random(-mWidth, mWidth);
309 blades[index + BLADE_STRUCT_XPOS] = xpos;
310 blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f;
311 blades[index + BLADE_STRUCT_YPOS] = mHeight;
312 }
313
Romain Guyb7d22522009-08-20 12:08:50 -0700314 private int createBlade(float[] blades, int index) {
315 final float size = random(4.0f) + 4.0f;
Romain Guy44da1782009-08-28 11:03:21 -0700316 final int xpos = random(-mWidth, mWidth);
Romain Guyb7d22522009-08-20 12:08:50 -0700317
Romain Guy55a384c2009-08-12 10:58:02 -0700318 //noinspection PointlessArithmeticExpression
319 blades[index + BLADE_STRUCT_ANGLE] = 0.0f;
Romain Guyb7d22522009-08-20 12:08:50 -0700320 blades[index + BLADE_STRUCT_SIZE] = size / TESSELATION;
321 blades[index + BLADE_STRUCT_XPOS] = xpos;
Romain Guy55a384c2009-08-12 10:58:02 -0700322 blades[index + BLADE_STRUCT_YPOS] = mHeight;
323 blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f;
Romain Guyb7d22522009-08-20 12:08:50 -0700324 blades[index + BLADE_STRUCT_SCALE] = 4.0f / (size / TESSELATION) +
325 (random(0.6f) + 0.2f) * TESSELATION;
326 blades[index + BLADE_STRUCT_LENGTHX] = (random(4.5f) + 3.0f) * TESSELATION * size;
327 blades[index + BLADE_STRUCT_LENGTHY] = (random(5.5f) + 2.0f) * TESSELATION * size;
328 blades[index + BLADE_STRUCT_HARDNESS] = (random(1.0f) + 0.2f) * TESSELATION;
Romain Guy55a384c2009-08-12 10:58:02 -0700329 blades[index + BLADE_STRUCT_H] = random(0.02f) + 0.2f;
330 blades[index + BLADE_STRUCT_S] = random(0.22f) + 0.78f;
331 blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f;
Romain Guyb7d22522009-08-20 12:08:50 -0700332 blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f;
333
334 // Each blade is made of "size" quads, so we double to count the triangles
335 return (int) (blades[index + BLADE_STRUCT_SIZE]) * 2;
Romain Guy55a384c2009-08-12 10:58:02 -0700336 }
337
338 private void loadTextures() {
339 mTextures = new Allocation[TEXTURES_COUNT];
340
341 final Allocation[] textures = mTextures;
342 textures[0] = loadTexture(R.drawable.night, "TNight");
343 textures[1] = loadTexture(R.drawable.sunrise, "TSunrise");
344 textures[2] = loadTexture(R.drawable.sky, "TSky");
345 textures[3] = loadTexture(R.drawable.sunset, "TSunset");
346 textures[4] = generateTextureAlpha(4, 1, new int[] { 0x00FFFF00 }, "TAa");
347
348 final int count = textures.length;
349 for (int i = 0; i < count; i++) {
Romain Guyb7d22522009-08-20 12:08:50 -0700350 textures[i].uploadToTexture(0);
Romain Guy55a384c2009-08-12 10:58:02 -0700351 }
352 }
353
354 private Allocation generateTextureAlpha(int width, int height, int[] data, String name) {
Jason Sams575d5142009-09-27 17:51:22 -0700355 final Type.Builder builder = new Type.Builder(mRS, A_8(mRS));
Romain Guy55a384c2009-08-12 10:58:02 -0700356 builder.add(Dimension.X, width);
357 builder.add(Dimension.Y, height);
Jason Sams575d5142009-09-27 17:51:22 -0700358
Romain Guy55a384c2009-08-12 10:58:02 -0700359 final Allocation allocation = Allocation.createTyped(mRS, builder.create());
360 allocation.data(data);
361 allocation.setName(name);
362 return allocation;
363 }
364
365 private Allocation loadTexture(int id, String name) {
366 final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
Jason Sams575d5142009-09-27 17:51:22 -0700367 id, RGB_565(mRS), false);
Romain Guy55a384c2009-08-12 10:58:02 -0700368 allocation.setName(name);
369 return allocation;
370 }
371
372 private void createProgramFragment() {
Romain Guyb7d22522009-08-20 12:08:50 -0700373 Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
374 samplerBuilder.setMin(LINEAR);
375 samplerBuilder.setMag(LINEAR);
376 samplerBuilder.setWrapS(WRAP);
377 samplerBuilder.setWrapT(WRAP);
Romain Guyff41eed2009-08-24 13:55:57 -0700378 mSampler = samplerBuilder.create();
Romain Guy55a384c2009-08-12 10:58:02 -0700379
Romain Guyb7d22522009-08-20 12:08:50 -0700380 ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
381 builder.setTexEnable(true, 0);
382 builder.setTexEnvMode(REPLACE, 0);
383 mPfBackground = builder.create();
Romain Guy55a384c2009-08-12 10:58:02 -0700384 mPfBackground.setName("PFBackground");
Romain Guyff41eed2009-08-24 13:55:57 -0700385 mPfBackground.bindSampler(mSampler, 0);
Romain Guy55a384c2009-08-12 10:58:02 -0700386 }
387
388 private void createProgramFragmentStore() {
Romain Guyb7d22522009-08-20 12:08:50 -0700389 ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
390 builder.setDepthFunc(ALWAYS);
391 builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
392 builder.setDitherEnable(false);
393 builder.setDepthMask(false);
394 mPfsBackground = builder.create();
Romain Guy55a384c2009-08-12 10:58:02 -0700395 mPfsBackground.setName("PFSBackground");
396 }
397
398 private void createProgramVertex() {
Romain Guyff41eed2009-08-24 13:55:57 -0700399 mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
400 mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
Romain Guy55a384c2009-08-12 10:58:02 -0700401
402 ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
403 pvb.setTextureMatrixEnable(true);
404 mPvBackground = pvb.create();
Romain Guyff41eed2009-08-24 13:55:57 -0700405 mPvBackground.bindAllocation(mPvOrthoAlloc);
Romain Guy55a384c2009-08-12 10:58:02 -0700406 mPvBackground.setName("PVBackground");
407 }
Romain Guya56ce012009-10-13 17:05:45 -0700408
409 private void updateLocation() {
410 updateLocation(mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
411 }
412
413 private void updateLocation(Location location) {
414 if (location != null) {
415 final String timeZone = Time.getCurrentTimezone();
416 final SunCalculator calculator = new SunCalculator(location, timeZone);
417 final Calendar now = Calendar.getInstance();
418
419 final double sunrise = calculator.computeSunriseTime(SunCalculator.ZENITH_CIVIL, now);
420 mWorldState.dawn = SunCalculator.timeToDayFraction(sunrise);
421
422 final double sunset = calculator.computeSunsetTime(SunCalculator.ZENITH_CIVIL, now);
423 mWorldState.dusk = SunCalculator.timeToDayFraction(sunset);
424 } else {
425 mWorldState.dawn = 0.3f;
426 mWorldState.dusk = 0.75f;
427 }
428
429 mWorldState.morning = mWorldState.dawn + 1.0f / 12.0f; // 2 hours for sunrise
430 mWorldState.afternoon = mWorldState.dusk - 1.0f / 12.0f; // 2 hours for sunset
431
432 // Send the new data to RenderScript
433 mState.data(mWorldState);
434 }
435
436 private class LocationUpdater implements LocationListener {
437 public void onLocationChanged(Location location) {
438 updateLocation(location);
439 }
440
441 public void onStatusChanged(String provider, int status, Bundle extras) {
442 }
443
444 public void onProviderEnabled(String provider) {
445 }
446
447 public void onProviderDisabled(String provider) {
448 }
449 }
450
451 private class TimezoneTracker extends BroadcastReceiver {
452 public void onReceive(Context context, Intent intent) {
453 getScript().setTimeZone(Time.getCurrentTimezone());
454 updateLocation();
455 }
456 }
Romain Guy55a384c2009-08-12 10:58:02 -0700457}