blob: df91decb31ed4faeafe296a3c5c038b0b6b84ad5 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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.server;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.pm.PackageManager;
Jeff Brown7f6c2312012-04-13 20:38:38 -070024import android.database.ContentObserver;
25import android.hardware.input.InputManager;
Joe Onorato95e4f702009-03-24 19:29:09 -070026import android.os.Handler;
Mike Lockwood3a322132009-11-24 00:30:52 -050027import android.os.IVibratorService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.PowerManager;
29import android.os.Process;
30import android.os.RemoteException;
31import android.os.IBinder;
32import android.os.Binder;
33import android.os.SystemClock;
Jeff Brownd4935962012-09-25 13:27:20 -070034import android.os.UserHandle;
Jeff Brown7f6c2312012-04-13 20:38:38 -070035import android.os.Vibrator;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070036import android.os.WorkSource;
Jeff Brown7f6c2312012-04-13 20:38:38 -070037import android.provider.Settings;
38import android.provider.Settings.SettingNotFoundException;
Joe Onorato8a9b2202010-02-26 18:56:32 -080039import android.util.Slog;
Jeff Brown7f6c2312012-04-13 20:38:38 -070040import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041
Jeff Brown7f6c2312012-04-13 20:38:38 -070042import java.util.ArrayList;
Patrick Scott18dd5f02009-07-02 11:31:12 -040043import java.util.LinkedList;
44import java.util.ListIterator;
45
Jeff Brown7f6c2312012-04-13 20:38:38 -070046public class VibratorService extends IVibratorService.Stub
47 implements InputManager.InputDeviceListener {
Mike Lockwood3a322132009-11-24 00:30:52 -050048 private static final String TAG = "VibratorService";
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -050049
Patrick Scott18dd5f02009-07-02 11:31:12 -040050 private final LinkedList<Vibration> mVibrations;
51 private Vibration mCurrentVibration;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070052 private final WorkSource mTmpWorkSource = new WorkSource();
Jeff Brown7f6c2312012-04-13 20:38:38 -070053 private final Handler mH = new Handler();
54
55 private final Context mContext;
56 private final PowerManager.WakeLock mWakeLock;
57 private InputManager mIm;
58
59 volatile VibrateThread mThread;
60
61 // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are
62 // to be acquired
63 private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
64 private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
65 private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
66
67 native static boolean vibratorExists();
68 native static void vibratorOn(long milliseconds);
69 native static void vibratorOff();
Patrick Scott18dd5f02009-07-02 11:31:12 -040070
Patrick Scott18dd5f02009-07-02 11:31:12 -040071 private class Vibration implements IBinder.DeathRecipient {
72 private final IBinder mToken;
73 private final long mTimeout;
74 private final long mStartTime;
75 private final long[] mPattern;
76 private final int mRepeat;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070077 private final int mUid;
Patrick Scott18dd5f02009-07-02 11:31:12 -040078
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070079 Vibration(IBinder token, long millis, int uid) {
80 this(token, millis, null, 0, uid);
Patrick Scott18dd5f02009-07-02 11:31:12 -040081 }
82
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070083 Vibration(IBinder token, long[] pattern, int repeat, int uid) {
84 this(token, 0, pattern, repeat, uid);
Patrick Scott18dd5f02009-07-02 11:31:12 -040085 }
86
87 private Vibration(IBinder token, long millis, long[] pattern,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070088 int repeat, int uid) {
Patrick Scott18dd5f02009-07-02 11:31:12 -040089 mToken = token;
90 mTimeout = millis;
91 mStartTime = SystemClock.uptimeMillis();
92 mPattern = pattern;
93 mRepeat = repeat;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070094 mUid = uid;
Patrick Scott18dd5f02009-07-02 11:31:12 -040095 }
96
97 public void binderDied() {
98 synchronized (mVibrations) {
99 mVibrations.remove(this);
100 if (this == mCurrentVibration) {
101 doCancelVibrateLocked();
102 startNextVibrationLocked();
103 }
104 }
105 }
106
107 public boolean hasLongerTimeout(long millis) {
108 if (mTimeout == 0) {
109 // This is a pattern, return false to play the simple
110 // vibration.
111 return false;
112 }
113 if ((mStartTime + mTimeout)
114 < (SystemClock.uptimeMillis() + millis)) {
115 // If this vibration will end before the time passed in, let
116 // the new vibration play.
117 return false;
118 }
119 return true;
120 }
121 }
122
Mike Lockwood3a322132009-11-24 00:30:52 -0500123 VibratorService(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 // Reset the hardware to a default state, in case this is a runtime
125 // restart instead of a fresh boot.
126 vibratorOff();
127
128 mContext = context;
129 PowerManager pm = (PowerManager)context.getSystemService(
130 Context.POWER_SERVICE);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700131 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 mWakeLock.setReferenceCounted(true);
133
Patrick Scott18dd5f02009-07-02 11:31:12 -0400134 mVibrations = new LinkedList<Vibration>();
135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 IntentFilter filter = new IntentFilter();
137 filter.addAction(Intent.ACTION_SCREEN_OFF);
138 context.registerReceiver(mIntentReceiver, filter);
139 }
140
Jeff Brown7f6c2312012-04-13 20:38:38 -0700141 public void systemReady() {
142 mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
Jeff Brownd4935962012-09-25 13:27:20 -0700143
Jeff Brown7f6c2312012-04-13 20:38:38 -0700144 mContext.getContentResolver().registerContentObserver(
145 Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true,
146 new ContentObserver(mH) {
147 @Override
148 public void onChange(boolean selfChange) {
Jeff Brown82065252012-04-16 13:19:05 -0700149 updateInputDeviceVibrators();
Jeff Brown7f6c2312012-04-13 20:38:38 -0700150 }
Jeff Brownd4935962012-09-25 13:27:20 -0700151 }, UserHandle.USER_ALL);
152
153 mContext.registerReceiver(new BroadcastReceiver() {
154 @Override
155 public void onReceive(Context context, Intent intent) {
156 updateInputDeviceVibrators();
157 }
158 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
159
Jeff Brown82065252012-04-16 13:19:05 -0700160 updateInputDeviceVibrators();
Dianne Hackbornea9020e2010-11-04 11:39:12 -0700161 }
Jeff Brown7f6c2312012-04-13 20:38:38 -0700162
163 public boolean hasVibrator() {
164 return doVibratorExists();
165 }
166
Patrick Scott18dd5f02009-07-02 11:31:12 -0400167 public void vibrate(long milliseconds, IBinder token) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700168 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
169 != PackageManager.PERMISSION_GRANTED) {
170 throw new SecurityException("Requires VIBRATE permission");
171 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700172 int uid = Binder.getCallingUid();
Patrick Scott24f10762009-08-19 09:03:56 -0400173 // We're running in the system server so we cannot crash. Check for a
174 // timeout of 0 or negative. This will ensure that a vibration has
175 // either a timeout of > 0 or a non-null pattern.
176 if (milliseconds <= 0 || (mCurrentVibration != null
177 && mCurrentVibration.hasLongerTimeout(milliseconds))) {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400178 // Ignore this vibration since the current vibration will play for
179 // longer than milliseconds.
180 return;
181 }
Jeff Brown7f6c2312012-04-13 20:38:38 -0700182
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700183 Vibration vib = new Vibration(token, milliseconds, uid);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400184 synchronized (mVibrations) {
185 removeVibrationLocked(token);
186 doCancelVibrateLocked();
187 mCurrentVibration = vib;
188 startVibrationLocked(vib);
189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 }
191
192 private boolean isAll0(long[] pattern) {
193 int N = pattern.length;
194 for (int i = 0; i < N; i++) {
195 if (pattern[i] != 0) {
196 return false;
197 }
198 }
199 return true;
200 }
201
202 public void vibratePattern(long[] pattern, int repeat, IBinder token) {
203 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
204 != PackageManager.PERMISSION_GRANTED) {
205 throw new SecurityException("Requires VIBRATE permission");
206 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700207 int uid = Binder.getCallingUid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 // so wakelock calls will succeed
209 long identity = Binder.clearCallingIdentity();
210 try {
211 if (false) {
212 String s = "";
213 int N = pattern.length;
214 for (int i=0; i<N; i++) {
215 s += " " + pattern[i];
216 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800217 Slog.i(TAG, "vibrating with pattern: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 }
219
220 // we're running in the server so we can't fail
221 if (pattern == null || pattern.length == 0
222 || isAll0(pattern)
223 || repeat >= pattern.length || token == null) {
224 return;
225 }
226
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700227 Vibration vib = new Vibration(token, pattern, repeat, uid);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400228 try {
229 token.linkToDeath(vib, 0);
230 } catch (RemoteException e) {
231 return;
232 }
233
234 synchronized (mVibrations) {
235 removeVibrationLocked(token);
236 doCancelVibrateLocked();
237 if (repeat >= 0) {
238 mVibrations.addFirst(vib);
239 startNextVibrationLocked();
240 } else {
241 // A negative repeat means that this pattern is not meant
242 // to repeat. Treat it like a simple vibration.
243 mCurrentVibration = vib;
244 startVibrationLocked(vib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 }
247 }
248 finally {
249 Binder.restoreCallingIdentity(identity);
250 }
251 }
252
Patrick Scott18dd5f02009-07-02 11:31:12 -0400253 public void cancelVibrate(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 mContext.enforceCallingOrSelfPermission(
255 android.Manifest.permission.VIBRATE,
256 "cancelVibrate");
257
258 // so wakelock calls will succeed
259 long identity = Binder.clearCallingIdentity();
260 try {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400261 synchronized (mVibrations) {
262 final Vibration vib = removeVibrationLocked(token);
263 if (vib == mCurrentVibration) {
264 doCancelVibrateLocked();
265 startNextVibrationLocked();
266 }
267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 }
269 finally {
270 Binder.restoreCallingIdentity(identity);
271 }
272 }
Eric Olsenf42f15c2009-10-29 16:42:03 -0700273
Patrick Scott18dd5f02009-07-02 11:31:12 -0400274 private final Runnable mVibrationRunnable = new Runnable() {
275 public void run() {
276 synchronized (mVibrations) {
277 doCancelVibrateLocked();
278 startNextVibrationLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
Patrick Scott18dd5f02009-07-02 11:31:12 -0400280 }
281 };
282
283 // Lock held on mVibrations
284 private void doCancelVibrateLocked() {
285 if (mThread != null) {
286 synchronized (mThread) {
287 mThread.mDone = true;
288 mThread.notify();
289 }
290 mThread = null;
291 }
Jeff Brown7f6c2312012-04-13 20:38:38 -0700292 doVibratorOff();
Patrick Scott18dd5f02009-07-02 11:31:12 -0400293 mH.removeCallbacks(mVibrationRunnable);
294 }
295
296 // Lock held on mVibrations
297 private void startNextVibrationLocked() {
298 if (mVibrations.size() <= 0) {
Mathias Jeppssonb23949b2010-09-28 14:45:23 +0200299 mCurrentVibration = null;
Patrick Scott18dd5f02009-07-02 11:31:12 -0400300 return;
301 }
302 mCurrentVibration = mVibrations.getFirst();
303 startVibrationLocked(mCurrentVibration);
304 }
305
306 // Lock held on mVibrations
307 private void startVibrationLocked(final Vibration vib) {
308 if (vib.mTimeout != 0) {
Jeff Brown7f6c2312012-04-13 20:38:38 -0700309 doVibratorOn(vib.mTimeout);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400310 mH.postDelayed(mVibrationRunnable, vib.mTimeout);
311 } else {
312 // mThread better be null here. doCancelVibrate should always be
313 // called before startNextVibrationLocked or startVibrationLocked.
314 mThread = new VibrateThread(vib);
315 mThread.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
317 }
318
Patrick Scott18dd5f02009-07-02 11:31:12 -0400319 // Lock held on mVibrations
320 private Vibration removeVibrationLocked(IBinder token) {
321 ListIterator<Vibration> iter = mVibrations.listIterator(0);
322 while (iter.hasNext()) {
323 Vibration vib = iter.next();
324 if (vib.mToken == token) {
325 iter.remove();
Mathias Jeppssonb23949b2010-09-28 14:45:23 +0200326 unlinkVibration(vib);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400327 return vib;
328 }
329 }
330 // We might be looking for a simple vibration which is only stored in
331 // mCurrentVibration.
332 if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
Mathias Jeppssonb23949b2010-09-28 14:45:23 +0200333 unlinkVibration(mCurrentVibration);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400334 return mCurrentVibration;
335 }
336 return null;
337 }
338
Mathias Jeppssonb23949b2010-09-28 14:45:23 +0200339 private void unlinkVibration(Vibration vib) {
340 if (vib.mPattern != null) {
341 // If Vibration object has a pattern,
342 // the Vibration object has also been linkedToDeath.
343 vib.mToken.unlinkToDeath(vib, 0);
344 }
345 }
346
Jeff Brown7f6c2312012-04-13 20:38:38 -0700347 private void updateInputDeviceVibrators() {
348 synchronized (mVibrations) {
349 doCancelVibrateLocked();
350
351 synchronized (mInputDeviceVibrators) {
Jeff Brown82065252012-04-16 13:19:05 -0700352 mVibrateInputDevicesSetting = false;
353 try {
Jeff Brownd4935962012-09-25 13:27:20 -0700354 mVibrateInputDevicesSetting = Settings.System.getIntForUser(
355 mContext.getContentResolver(),
356 Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
Jeff Brown82065252012-04-16 13:19:05 -0700357 } catch (SettingNotFoundException snfe) {
358 }
359
360 if (mVibrateInputDevicesSetting) {
361 if (!mInputDeviceListenerRegistered) {
362 mInputDeviceListenerRegistered = true;
363 mIm.registerInputDeviceListener(this, mH);
364 }
365 } else {
366 if (mInputDeviceListenerRegistered) {
367 mInputDeviceListenerRegistered = false;
368 mIm.unregisterInputDeviceListener(this);
369 }
370 }
371
Jeff Brown7f6c2312012-04-13 20:38:38 -0700372 mInputDeviceVibrators.clear();
373 if (mVibrateInputDevicesSetting) {
374 int[] ids = mIm.getInputDeviceIds();
375 for (int i = 0; i < ids.length; i++) {
376 InputDevice device = mIm.getInputDevice(ids[i]);
377 Vibrator vibrator = device.getVibrator();
378 if (vibrator.hasVibrator()) {
379 mInputDeviceVibrators.add(vibrator);
380 }
381 }
382 }
383 }
384
385 startNextVibrationLocked();
386 }
387 }
388
389 @Override
390 public void onInputDeviceAdded(int deviceId) {
391 updateInputDeviceVibrators();
392 }
393
394 @Override
395 public void onInputDeviceChanged(int deviceId) {
396 updateInputDeviceVibrators();
397 }
398
399 @Override
400 public void onInputDeviceRemoved(int deviceId) {
401 updateInputDeviceVibrators();
402 }
403
404 private boolean doVibratorExists() {
Jeff Brown1064a502012-05-02 16:51:37 -0700405 // For now, we choose to ignore the presence of input devices that have vibrators
406 // when reporting whether the device has a vibrator. Applications often use this
407 // information to decide whether to enable certain features so they expect the
408 // result of hasVibrator() to be constant. For now, just report whether
409 // the device has a built-in vibrator.
410 //synchronized (mInputDeviceVibrators) {
411 // return !mInputDeviceVibrators.isEmpty() || vibratorExists();
412 //}
413 return vibratorExists();
Jeff Brown7f6c2312012-04-13 20:38:38 -0700414 }
415
416 private void doVibratorOn(long millis) {
417 synchronized (mInputDeviceVibrators) {
418 final int vibratorCount = mInputDeviceVibrators.size();
419 if (vibratorCount != 0) {
420 for (int i = 0; i < vibratorCount; i++) {
421 mInputDeviceVibrators.get(i).vibrate(millis);
422 }
423 } else {
424 vibratorOn(millis);
425 }
426 }
427 }
428
429 private void doVibratorOff() {
430 synchronized (mInputDeviceVibrators) {
431 final int vibratorCount = mInputDeviceVibrators.size();
432 if (vibratorCount != 0) {
433 for (int i = 0; i < vibratorCount; i++) {
434 mInputDeviceVibrators.get(i).cancel();
435 }
436 } else {
437 vibratorOff();
438 }
439 }
440 }
441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 private class VibrateThread extends Thread {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400443 final Vibration mVibration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 boolean mDone;
Eric Olsenf42f15c2009-10-29 16:42:03 -0700445
Patrick Scott18dd5f02009-07-02 11:31:12 -0400446 VibrateThread(Vibration vib) {
447 mVibration = vib;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700448 mTmpWorkSource.set(vib.mUid);
449 mWakeLock.setWorkSource(mTmpWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 mWakeLock.acquire();
451 }
452
453 private void delay(long duration) {
454 if (duration > 0) {
Vairavan Srinivasane4c56d92011-03-31 13:32:54 -0700455 long bedtime = duration + SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 do {
457 try {
458 this.wait(duration);
459 }
460 catch (InterruptedException e) {
461 }
462 if (mDone) {
463 break;
464 }
Vairavan Srinivasane4c56d92011-03-31 13:32:54 -0700465 duration = bedtime - SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 } while (duration > 0);
467 }
468 }
469
470 public void run() {
471 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
472 synchronized (this) {
473 int index = 0;
Patrick Scott18dd5f02009-07-02 11:31:12 -0400474 long[] pattern = mVibration.mPattern;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 int len = pattern.length;
Patrick Scott18dd5f02009-07-02 11:31:12 -0400476 int repeat = mVibration.mRepeat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 long duration = 0;
478
479 while (!mDone) {
Eric Olsenf42f15c2009-10-29 16:42:03 -0700480 // add off-time duration to any accumulated on-time duration
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 if (index < len) {
482 duration += pattern[index++];
483 }
484
485 // sleep until it is time to start the vibrator
486 delay(duration);
487 if (mDone) {
488 break;
489 }
490
491 if (index < len) {
492 // read on-time duration and start the vibrator
493 // duration is saved for delay() at top of loop
494 duration = pattern[index++];
495 if (duration > 0) {
Jeff Brown7f6c2312012-04-13 20:38:38 -0700496 VibratorService.this.doVibratorOn(duration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
498 } else {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400499 if (repeat < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 break;
501 } else {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400502 index = repeat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 duration = 0;
504 }
505 }
506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 mWakeLock.release();
508 }
Patrick Scott18dd5f02009-07-02 11:31:12 -0400509 synchronized (mVibrations) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 if (mThread == this) {
511 mThread = null;
512 }
Patrick Scott18dd5f02009-07-02 11:31:12 -0400513 if (!mDone) {
514 // If this vibration finished naturally, start the next
515 // vibration.
516 mVibrations.remove(mVibration);
Mathias Jeppssonb23949b2010-09-28 14:45:23 +0200517 unlinkVibration(mVibration);
Patrick Scott18dd5f02009-07-02 11:31:12 -0400518 startNextVibrationLocked();
519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 }
521 }
522 };
523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
525 public void onReceive(Context context, Intent intent) {
526 if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Patrick Scott18dd5f02009-07-02 11:31:12 -0400527 synchronized (mVibrations) {
528 doCancelVibrateLocked();
Vairavan Srinivasan8a61f492011-05-13 10:47:20 -0700529
530 int size = mVibrations.size();
531 for(int i = 0; i < size; i++) {
532 unlinkVibration(mVibrations.get(i));
533 }
534
Patrick Scott18dd5f02009-07-02 11:31:12 -0400535 mVibrations.clear();
536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 }
538 }
539 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540}