VibratorService.java revision a06de0f29b58df9246779cc4bfd8f06f7205ddb6
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 257f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.database.ContentObserver; 267f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.hardware.input.InputManager; 2795e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 283a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 34a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 36d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 377f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 387e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 397f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 407f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 418a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 427f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 44a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 477f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 4818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 4918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 5018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 517f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 533a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 54cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 5518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final LinkedList<Vibration> mVibrations; 5618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration mCurrentVibration; 577e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 63a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown volatile VibrateThread mThread; 677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 74a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 75a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 7918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 8018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 8118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 8218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mTimeout; 8318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mStartTime; 8418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long[] mPattern; 8518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final int mRepeat; 867e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final int mUid; 87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final String mPackageName; 8818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration(IBinder token, long millis, int uid, String packageName) { 90a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn this(token, millis, null, 0, uid, packageName); 9118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 9218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration(IBinder token, long[] pattern, int repeat, int uid, String packageName) { 94a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn this(token, 0, pattern, repeat, uid, packageName); 9518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 9618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 9718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration(IBinder token, long millis, long[] pattern, 98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn int repeat, int uid, String packageName) { 9918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mTimeout = millis; 10118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 10218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mPattern = pattern; 10318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mRepeat = repeat; 1047e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 105a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mPackageName = packageName; 10618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 10718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 10818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(this); 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 11318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 11418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 11918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mTimeout == 0) { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // This is a pattern, return false to play the simple 12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if ((mStartTime + mTimeout) 12518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott < (SystemClock.uptimeMillis() + millis)) { 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration will end before the time passed in, let 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // the new vibration play. 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return true; 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1343a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService( 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.POWER_SERVICE); 1427e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 145a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 146a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 147a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 14818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations = new LinkedList<Vibration>(); 14918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 1567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE); 157d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 1587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 1597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true, 1607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown new ContentObserver(mH) { 1617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 1627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onChange(boolean selfChange) { 1638206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 1647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 165d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, UserHandle.USER_ALL); 166d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 167d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 168d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 169d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 170d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown updateInputDeviceVibrators(); 171d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 172d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 173d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 1748206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 1757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 1767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 177ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 1787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 179ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 1807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 181a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void vibrate(String packageName, long milliseconds, IBinder token) { 182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1867e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn int uid = Binder.getCallingUid(); 18724f1076097588b7db1269044fb55af58bc420e58Patrick Scott // We're running in the system server so we cannot crash. Check for a 18824f1076097588b7db1269044fb55af58bc420e58Patrick Scott // timeout of 0 or negative. This will ensure that a vibration has 18924f1076097588b7db1269044fb55af58bc420e58Patrick Scott // either a timeout of > 0 or a non-null pattern. 19024f1076097588b7db1269044fb55af58bc420e58Patrick Scott if (milliseconds <= 0 || (mCurrentVibration != null 19124f1076097588b7db1269044fb55af58bc420e58Patrick Scott && mCurrentVibration.hasLongerTimeout(milliseconds))) { 19218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Ignore this vibration since the current vibration will play for 19318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // longer than milliseconds. 19418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 19518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 1967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 197a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration vib = new Vibration(token, milliseconds, uid, packageName); 198a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 199a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 200a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 201a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (mVibrations) { 202a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn removeVibrationLocked(token); 203a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doCancelVibrateLocked(); 204a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = vib; 205a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn startVibrationLocked(vib); 206a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 207a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } finally { 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.restoreCallingIdentity(ident); 20918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAll0(long[] pattern) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern[i] != 0) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 222a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void vibratePattern(String packageName, long[] pattern, int repeat, IBinder token) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2277e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn int uid = Binder.getCallingUid(); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (false) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ""; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s += " " + pattern[i]; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2378a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "vibrating with pattern: " + s); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we're running in the server so we can't fail 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern == null || pattern.length == 0 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || isAll0(pattern) 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || repeat >= pattern.length || token == null) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration vib = new Vibration(token, pattern, repeat, uid, packageName); 24818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 24918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 25018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 25118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 25218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 25518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott removeVibrationLocked(token); 25618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 25718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat >= 0) { 25818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.addFirst(vib); 25918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 26018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 26118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // A negative repeat means that this pattern is not meant 26218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // to repeat. Treat it like a simple vibration. 26318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = vib; 26418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(vib); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 28118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 28218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration vib = removeVibrationLocked(token); 28318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib == mCurrentVibration) { 28418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 28518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 28618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 28718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 293f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 29418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final Runnable mVibrationRunnable = new Runnable() { 29518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 29618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 29718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 29818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 29918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 30018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 30118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 30218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 30318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 30418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 30518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 30618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mThread) { 30718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.mDone = true; 30818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.notify(); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 31318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.removeCallbacks(mVibrationRunnable); 314a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 31518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 31618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 31718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 31818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startNextVibrationLocked() { 31918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mVibrations.size() <= 0) { 320a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 321b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson mCurrentVibration = null; 32218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 32318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 32418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = mVibrations.getFirst(); 32518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(mCurrentVibration); 32618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 32718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 32818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 32918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 330a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 331a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn int mode = mAppOpsService.startOperation(AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName); 332a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode != AppOpsManager.MODE_ALLOWED) { 333a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode == AppOpsManager.MODE_ERRORED) { 334a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 335a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 336a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mH.post(mVibrationRunnable); 337a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 338a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 339a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 340a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 34118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mTimeout != 0) { 342a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doVibratorOn(vib.mTimeout, vib.mUid); 34318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.postDelayed(mVibrationRunnable, vib.mTimeout); 34418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 34518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 34618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 34718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = new VibrateThread(vib); 34818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 34918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 35018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 35118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 352a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 353a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 354a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 355a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService.finishOperation(AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 356a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration.mPackageName); 357a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 358a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 359a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 360a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 361a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 362a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 36318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 36418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration removeVibrationLocked(IBinder token) { 36518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott ListIterator<Vibration> iter = mVibrations.listIterator(0); 36618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott while (iter.hasNext()) { 36718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott Vibration vib = iter.next(); 36818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mToken == token) { 36918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott iter.remove(); 370b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(vib); 37118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return vib; 37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 37418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // We might be looking for a simple vibration which is only stored in 37518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mCurrentVibration. 37618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 377b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mCurrentVibration); 37818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return mCurrentVibration; 37918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return null; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 383b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 384b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson if (vib.mPattern != null) { 385b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // If Vibration object has a pattern, 386b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // the Vibration object has also been linkedToDeath. 387b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 388b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 389b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 390b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 3917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void updateInputDeviceVibrators() { 3927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mVibrations) { 3937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doCancelVibrateLocked(); 3947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 3957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 3968206525b242ceb012d882849c4e355223ba81b9dJeff Brown mVibrateInputDevicesSetting = false; 3978206525b242ceb012d882849c4e355223ba81b9dJeff Brown try { 398d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mVibrateInputDevicesSetting = Settings.System.getIntForUser( 399d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.getContentResolver(), 400d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 4018206525b242ceb012d882849c4e355223ba81b9dJeff Brown } catch (SettingNotFoundException snfe) { 4028206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4038206525b242ceb012d882849c4e355223ba81b9dJeff Brown 4048206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mVibrateInputDevicesSetting) { 4058206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (!mInputDeviceListenerRegistered) { 4068206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = true; 4078206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.registerInputDeviceListener(this, mH); 4088206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4098206525b242ceb012d882849c4e355223ba81b9dJeff Brown } else { 4108206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mInputDeviceListenerRegistered) { 4118206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = false; 4128206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.unregisterInputDeviceListener(this); 4138206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4148206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4158206525b242ceb012d882849c4e355223ba81b9dJeff Brown 4167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.clear(); 4177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (mVibrateInputDevicesSetting) { 4187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown int[] ids = mIm.getInputDeviceIds(); 4197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < ids.length; i++) { 4207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown InputDevice device = mIm.getInputDevice(ids[i]); 4217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Vibrator vibrator = device.getVibrator(); 4227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibrator.hasVibrator()) { 4237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.add(vibrator); 4247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4277f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown startNextVibrationLocked(); 4307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 4357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 4407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4437f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 4457f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 4491064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 4501064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 4511064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 4521064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 4531064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 4541064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 4551064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 4561064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 4571064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown return vibratorExists(); 4587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 460a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void doVibratorOn(long millis, int uid) { 4617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 462a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 463a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOn(uid, millis); 464a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = uid; 465a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 466a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 4687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 4697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 4707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).vibrate(millis); 4717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 4737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 4747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 4797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 480a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurVibUid >= 0) { 481a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 482a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOff(mCurVibUid); 483a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 484a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 485a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = -1; 486a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 4887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 4897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 4907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 4917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 4937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 4947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 49918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration mVibration; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mDone; 501f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 50218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott VibrateThread(Vibration vib) { 50318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibration = vib; 5047e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mTmpWorkSource.set(vib.mUid); 5057e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void delay(long duration) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 511e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan long bedtime = duration + SystemClock.uptimeMillis(); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(duration); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 521e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan duration = bedtime - SystemClock.uptimeMillis(); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (duration > 0); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 529a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long[] pattern = mVibration.mPattern; 530a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int len = pattern.length; 531a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int repeat = mVibration.mRepeat; 532a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int uid = mVibration.mUid; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = 0; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mDone) { 537f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen // add off-time duration to any accumulated on-time duration 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration += pattern[index++]; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sleep until it is time to start the vibrator 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay(duration); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read on-time duration and start the vibrator 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // duration is saved for delay() at top of loop 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = pattern[index++]; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 553a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn VibratorService.this.doVibratorOn(duration, uid); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 55618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat < 0) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 55918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott index = repeat; 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = 0; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 56618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThread == this) { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread = null; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 57018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (!mDone) { 57118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration finished naturally, start the next 57218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 57318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(mVibration); 574b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mVibration); 57518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 57918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 58418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 58518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 5868a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 5878a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan int size = mVibrations.size(); 5888a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan for(int i = 0; i < size; i++) { 5898a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan unlinkVibration(mVibrations.get(i)); 5908a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 5918a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 59218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.clear(); 59318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 598