VibratorService.java revision 8ce2a538d9b94a0d8e1543c4ee4620a8af525276
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; 2791268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats; 2895e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 293a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 31eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 36a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 38d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 397f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 407e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 417f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 427f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 438a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 447f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 457b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 48a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 49a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 503a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor; 513a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter; 527f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 533a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays; 54969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator; 5518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 5618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 5718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 587f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 603a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 6182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 6218f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi private static final String SYSTEM_UI_PACKAGE = "com.android.systemui"; 63cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 6418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final LinkedList<Vibration> mVibrations; 653a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final LinkedList<VibrationInfo> mPreviousVibrations; 663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final int mPreviousVibrationsLimit; 6718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration mCurrentVibration; 687e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 73a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 74a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 75eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown volatile VibrateThread mThread; 797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 8713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 8813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 91e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker native static void vibratorInit(); 927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 9418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 9518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 9618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 9718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mTimeout; 9818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mStartTime; 9918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long[] mPattern; 10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final int mRepeat; 1017b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private final int mUsageHint; 1027e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final int mUid; 1038fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer private final String mOpPkg; 10418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1057b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long millis, int usageHint, int uid, String opPkg) { 1067b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, millis, null, 0, usageHint, uid, opPkg); 10718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 10818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1097b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long[] pattern, int repeat, int usageHint, int uid, 1108fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer String opPkg) { 1117b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, 0, pattern, repeat, usageHint, uid, opPkg); 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration(IBinder token, long millis, long[] pattern, 1157b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int repeat, int usageHint, int uid, String opPkg) { 11618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mTimeout = millis; 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 11918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mPattern = pattern; 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mRepeat = repeat; 1217b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1227e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1238fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(this); 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mTimeout == 0) { 13818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // This is a pattern, return false to play the simple 13918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 14018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 14118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 14218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if ((mStartTime + mTimeout) 14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott < (SystemClock.uptimeMillis() + millis)) { 14418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration will end before the time passed in, let 14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // the new vibration play. 14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 14718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 14818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return true; 14918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 150969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 151969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 15218f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg)) 15318f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi && mRepeat < 0; 154969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 15518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 15618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1573a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private static class VibrationInfo { 1583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long timeout; 1593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long startTime; 1603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long[] pattern; 1613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int repeat; 1623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint; 1633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int uid; 1643a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski String opPkg; 1653a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public VibrationInfo(long timeout, long startTime, long[] pattern, int repeat, 1673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint, int uid, String opPkg) { 1683a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.timeout = timeout; 1693a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.startTime = startTime; 1703a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.pattern = pattern; 1713a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.repeat = repeat; 1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.usageHint = usageHint; 1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.uid = uid; 1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.opPkg = opPkg; 1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 1783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public String toString() { 1793a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return new StringBuilder() 1803a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append("timeout: ") 1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(timeout) 1823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", startTime: ") 1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(startTime) 1843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", pattern: ") 1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(Arrays.toString(pattern)) 1863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", repeat: ") 1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(repeat) 1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", usageHint: ") 1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(usageHint) 1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", uid: ") 1913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(uid) 1923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", opPkg: ") 1933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(opPkg) 1943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .toString(); 1953a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1963a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1973a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1983a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 199e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker vibratorInit(); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService( 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.POWER_SERVICE); 2077e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 21191268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 21291268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 213a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 2143a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrationsLimit = mContext.getResources().getInteger( 2153a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski com.android.internal.R.integer.config_previousVibrationsDumpLimit); 2163a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2173a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mVibrations = new LinkedList<>(); 2183a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations = new LinkedList<>(); 21918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2268ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 22713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 228d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 229eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 230eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 231eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 232eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn @Override 233eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn public void onLowPowerModeChanged(boolean enabled) { 234eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn updateInputDeviceVibrators(); 235eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn } 236eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 237eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 23913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 24013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 24113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 242d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 243d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 244d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 245d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown updateInputDeviceVibrators(); 246d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 247d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 248d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2498206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 2507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 25213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 25313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 25413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 25513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 25613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 25713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi updateInputDeviceVibrators(); 26013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 26382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 264ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 266ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 268f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 269f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 270f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 271f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 272f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 273f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 274f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 275f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 276f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 277f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 278f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 27982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 2807b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock public void vibrate(int uid, String opPkg, long milliseconds, int usageHint, 2811af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock IBinder token) { 282105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 283105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 284105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 285105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 286f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 28724f1076097588b7db1269044fb55af58bc420e58Patrick Scott // We're running in the system server so we cannot crash. Check for a 28824f1076097588b7db1269044fb55af58bc420e58Patrick Scott // timeout of 0 or negative. This will ensure that a vibration has 28924f1076097588b7db1269044fb55af58bc420e58Patrick Scott // either a timeout of > 0 or a non-null pattern. 29024f1076097588b7db1269044fb55af58bc420e58Patrick Scott if (milliseconds <= 0 || (mCurrentVibration != null 29124f1076097588b7db1269044fb55af58bc420e58Patrick Scott && mCurrentVibration.hasLongerTimeout(milliseconds))) { 29218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Ignore this vibration since the current vibration will play for 29318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // longer than milliseconds. 29418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 29518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 29782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 29882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating for " + milliseconds + " ms."); 29982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 30082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown 3017b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg); 302a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 303a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 304a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 305a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (mVibrations) { 306a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn removeVibrationLocked(token); 307a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doCancelVibrateLocked(); 308a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = vib; 3093a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 310a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn startVibrationLocked(vib); 311a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 312a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } finally { 313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.restoreCallingIdentity(ident); 31418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAll0(long[] pattern) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern[i] != 0) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 328f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn public void vibratePattern(int uid, String packageName, long[] pattern, int repeat, 3297b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int usageHint, IBinder token) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 334f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 33882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ""; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s += " " + pattern[i]; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating with pattern:" + s); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we're running in the server so we can't fail 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern == null || pattern.length == 0 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || isAll0(pattern) 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || repeat >= pattern.length || token == null) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3547b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, pattern, repeat, usageHint, uid, packageName); 35518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 35618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 35718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 35818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 35918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 36218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott removeVibrationLocked(token); 36318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 36418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat >= 0) { 36518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.addFirst(vib); 36618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 36718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 36818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // A negative repeat means that this pattern is not meant 36918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // to repeat. Treat it like a simple vibration. 37018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = vib; 37118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(vib); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 3823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 3833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 3843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.addLast(new VibratorService.VibrationInfo(vib.mTimeout, vib.mStartTime, 3863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski vib.mPattern, vib.mRepeat, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 3873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 38982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 39018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 39818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 39918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration vib = removeVibrationLocked(token); 40018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib == mCurrentVibration) { 40182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 40282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Canceling vibration."); 40382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 40418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 40518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 40618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 40718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 413f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 41418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final Runnable mVibrationRunnable = new Runnable() { 41582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 41618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 41718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 41818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 41918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 42018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 42718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mThread) { 42818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.mDone = true; 42918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.notify(); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.removeCallbacks(mVibrationRunnable); 435a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startNextVibrationLocked() { 44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mVibrations.size() <= 0) { 441a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 442b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson mCurrentVibration = null; 44318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = mVibrations.getFirst(); 44618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(mCurrentVibration); 44718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 44918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 451a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 4527b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (mLowPowerMode 45389c3b29a9bfa0ae9858b913bc1ab6604c4613a15Jean-Michel Trivi && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 454664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi return; 455664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 45613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4571af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 4587b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock vib.mUsageHint, vib.mUid, vib.mOpPkg); 4591af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mode == AppOpsManager.MODE_ALLOWED) { 4601af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 4618fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 4621af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 463a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode != AppOpsManager.MODE_ALLOWED) { 464a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode == AppOpsManager.MODE_ERRORED) { 465a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 466a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 467a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mH.post(mVibrationRunnable); 468a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 469a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 470a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 471a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 47218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mTimeout != 0) { 4737b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint); 47418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.postDelayed(mVibrationRunnable, vib.mTimeout); 47518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 47618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 47718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 47818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = new VibrateThread(vib); 47918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 48018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 48118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 48218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 483a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 484a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 485a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 486e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 487e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 4888fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 489a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 490a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 491a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 492a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 493a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 494a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 49518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 49618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration removeVibrationLocked(IBinder token) { 49718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott ListIterator<Vibration> iter = mVibrations.listIterator(0); 49818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott while (iter.hasNext()) { 49918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott Vibration vib = iter.next(); 50018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mToken == token) { 50118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott iter.remove(); 502b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(vib); 50318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return vib; 50418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // We might be looking for a simple vibration which is only stored in 50718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mCurrentVibration. 50818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 509b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mCurrentVibration); 51018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return mCurrentVibration; 51118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 51218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return null; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 515b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 516b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson if (vib.mPattern != null) { 517b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // If Vibration object has a pattern, 518b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // the Vibration object has also been linkedToDeath. 519b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 520b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 521b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 522b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 5237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void updateInputDeviceVibrators() { 5247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mVibrations) { 5257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doCancelVibrateLocked(); 5267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5277f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 5288206525b242ceb012d882849c4e355223ba81b9dJeff Brown mVibrateInputDevicesSetting = false; 5298206525b242ceb012d882849c4e355223ba81b9dJeff Brown try { 530d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mVibrateInputDevicesSetting = Settings.System.getIntForUser( 531d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.getContentResolver(), 532d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 5338206525b242ceb012d882849c4e355223ba81b9dJeff Brown } catch (SettingNotFoundException snfe) { 5348206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5358206525b242ceb012d882849c4e355223ba81b9dJeff Brown 536eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled(); 53713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 5388206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mVibrateInputDevicesSetting) { 5398206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (!mInputDeviceListenerRegistered) { 5408206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = true; 5418206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.registerInputDeviceListener(this, mH); 5428206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5438206525b242ceb012d882849c4e355223ba81b9dJeff Brown } else { 5448206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mInputDeviceListenerRegistered) { 5458206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = false; 5468206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.unregisterInputDeviceListener(this); 5478206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5488206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5498206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.clear(); 5517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (mVibrateInputDevicesSetting) { 5527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown int[] ids = mIm.getInputDeviceIds(); 5537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < ids.length; i++) { 5547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown InputDevice device = mIm.getInputDevice(ids[i]); 5557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Vibrator vibrator = device.getVibrator(); 5567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibrator.hasVibrator()) { 5577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.add(vibrator); 5587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown startNextVibrationLocked(); 5647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 5697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 5747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 5797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 5831064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 5841064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 5851064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 5861064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 5871064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 5881064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 5891064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 5901064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 591c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 5927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5947b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private void doVibratorOn(long millis, int uid, int usageHint) { 5957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 59682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 59782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator on for " + millis + " ms."); 59882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 599a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 600a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOn(uid, millis); 601a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = uid; 602a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 603a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6067b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint) 6077b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .build(); 6087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6097b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 6107f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 6187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 61982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 62082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 62182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 622a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurVibUid >= 0) { 623a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 624a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOff(mCurVibUid); 625a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 626a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 627a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = -1; 628a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 6337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 6367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 64118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration mVibration; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mDone; 643f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 64418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott VibrateThread(Vibration vib) { 64518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibration = vib; 6467e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mTmpWorkSource.set(vib.mUid); 6477e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void delay(long duration) { 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 653e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan long bedtime = duration + SystemClock.uptimeMillis(); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(duration); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 663e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan duration = bedtime - SystemClock.uptimeMillis(); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (duration > 0); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 671a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long[] pattern = mVibration.mPattern; 672a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int len = pattern.length; 673a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int repeat = mVibration.mRepeat; 674a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int uid = mVibration.mUid; 6757b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final int usageHint = mVibration.mUsageHint; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = 0; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mDone) { 680f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen // add off-time duration to any accumulated on-time duration 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration += pattern[index++]; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sleep until it is time to start the vibrator 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay(duration); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read on-time duration and start the vibrator 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // duration is saved for delay() at top of loop 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = pattern[index++]; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 6967b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock VibratorService.this.doVibratorOn(duration, uid, usageHint); 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 69918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat < 0) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 70218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott index = repeat; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = 0; 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 70918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThread == this) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread = null; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 71318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (!mDone) { 71418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration finished naturally, start the next 71518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 716b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mVibration); 71718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 721969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 724969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 72718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 728969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 729969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 730969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 731969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 732969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 733969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 734969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 735969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 7368a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 7378a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 738969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // Clear all remaining vibrations. 739969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Iterator<Vibration> it = mVibrations.iterator(); 740969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown while (it.hasNext()) { 741969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Vibration vibration = it.next(); 742969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (vibration != mCurrentVibration) { 743969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown unlinkVibration(vibration); 744969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown it.remove(); 745969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 746969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 74718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 7513a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 7523a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 7533a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 7543a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 7553a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski != PackageManager.PERMISSION_GRANTED) { 7563a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 7573a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Permission Denial: can't dump vibrator service from from pid=" 7583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + Binder.getCallingPid() 7593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + ", uid=" + Binder.getCallingUid()); 7603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return; 7613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 7633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski synchronized (mVibrations) { 7643a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 7653a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 7663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 7673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7683a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7693a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 771