VibratorService.java revision a5281001dcd420e0d14ccb3d4872da0f200bc9b2
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; 272d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebingerimport android.media.AudioManager; 2891268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats; 2995e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 303a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 32eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 35a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ResultReceiver; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 38a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 39a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCallback; 40a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCommand; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 42d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 437f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 447e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 457f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 467f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 478a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 487f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 497b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 51a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 52a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 53a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 543a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor; 553a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter; 567f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 573a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays; 58969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator; 5918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 6018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 6118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 627f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 643a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 6582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 6618f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi private static final String SYSTEM_UI_PACKAGE = "com.android.systemui"; 67cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 6818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final LinkedList<Vibration> mVibrations; 693a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final LinkedList<VibrationInfo> mPreviousVibrations; 703a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final int mPreviousVibrationsLimit; 7118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration mCurrentVibration; 727e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 77a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 78a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 79eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown volatile VibrateThread mThread; 837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 90a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 9113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 9213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 95e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker native static void vibratorInit(); 967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 9818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 9918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 10118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mTimeout; 10218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mStartTime; 10318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long[] mPattern; 10418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final int mRepeat; 1057b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private final int mUsageHint; 1067e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final int mUid; 1078fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer private final String mOpPkg; 10818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1097b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long millis, int usageHint, int uid, String opPkg) { 1107b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, millis, null, 0, usageHint, uid, opPkg); 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1137b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long[] pattern, int repeat, int usageHint, int uid, 1148fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer String opPkg) { 1157b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, 0, pattern, repeat, usageHint, uid, opPkg); 11618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration(IBinder token, long millis, long[] pattern, 1197b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int repeat, int usageHint, int uid, String opPkg) { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mTimeout = millis; 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mPattern = pattern; 12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mRepeat = repeat; 1257b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1267e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1278fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(this); 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 14018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 14118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mTimeout == 0) { 14218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // This is a pattern, return false to play the simple 14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 14418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if ((mStartTime + mTimeout) 14718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott < (SystemClock.uptimeMillis() + millis)) { 14818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration will end before the time passed in, let 14918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // the new vibration play. 15018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 15118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 15218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return true; 15318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 154969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 155969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 15618f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg)) 15718f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi && mRepeat < 0; 158969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 15918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 16018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private static class VibrationInfo { 1623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long timeout; 1633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long startTime; 1643a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski long[] pattern; 1653a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int repeat; 1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint; 1673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int uid; 1683a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski String opPkg; 1693a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1703a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public VibrationInfo(long timeout, long startTime, long[] pattern, int repeat, 1713a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint, int uid, String opPkg) { 1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.timeout = timeout; 1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.startTime = startTime; 1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.pattern = pattern; 1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.repeat = repeat; 1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.usageHint = usageHint; 1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.uid = uid; 1783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski this.opPkg = opPkg; 1793a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1803a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 1823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public String toString() { 1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return new StringBuilder() 1843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append("timeout: ") 1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(timeout) 1863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", startTime: ") 1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(startTime) 1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", pattern: ") 1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(Arrays.toString(pattern)) 1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", repeat: ") 1913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(repeat) 1923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", usageHint: ") 1933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(usageHint) 1943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", uid: ") 1953a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(uid) 1963a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", opPkg: ") 1973a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(opPkg) 1983a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .toString(); 1993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 2003a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 2013a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2023a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 203e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker vibratorInit(); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService( 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.POWER_SERVICE); 2117e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 21591268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 21691268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 217a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 2183a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrationsLimit = mContext.getResources().getInteger( 2193a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski com.android.internal.R.integer.config_previousVibrationsDumpLimit); 2203a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2213a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mVibrations = new LinkedList<>(); 2223a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations = new LinkedList<>(); 22318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2308ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 23113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 232d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 233eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 234eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 235eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 236eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn @Override 237eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn public void onLowPowerModeChanged(boolean enabled) { 238eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn updateInputDeviceVibrators(); 239eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn } 240eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 241eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 24313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 24413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 24513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 246d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 247d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 248d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 249d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown updateInputDeviceVibrators(); 250d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 251d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 252d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2538206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 2547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 25613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 25713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 26113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 26213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 26313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi updateInputDeviceVibrators(); 26413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 26782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 268ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 270ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 272f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 273f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 274f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 275f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 276f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 277f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 278f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 279f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 280f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 281f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 282f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 28382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 2847b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock public void vibrate(int uid, String opPkg, long milliseconds, int usageHint, 2851af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock IBinder token) { 286105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 287105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 290f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 29124f1076097588b7db1269044fb55af58bc420e58Patrick Scott // We're running in the system server so we cannot crash. Check for a 29224f1076097588b7db1269044fb55af58bc420e58Patrick Scott // timeout of 0 or negative. This will ensure that a vibration has 29324f1076097588b7db1269044fb55af58bc420e58Patrick Scott // either a timeout of > 0 or a non-null pattern. 29424f1076097588b7db1269044fb55af58bc420e58Patrick Scott if (milliseconds <= 0 || (mCurrentVibration != null 29524f1076097588b7db1269044fb55af58bc420e58Patrick Scott && mCurrentVibration.hasLongerTimeout(milliseconds))) { 29618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Ignore this vibration since the current vibration will play for 29718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // longer than milliseconds. 29818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 29918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 30182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 30282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating for " + milliseconds + " ms."); 30382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 30482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown 3057b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg); 306a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 307a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 308a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 309a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (mVibrations) { 310a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn removeVibrationLocked(token); 311a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doCancelVibrateLocked(); 3123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn startVibrationLocked(vib); 314a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 315a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } finally { 316a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.restoreCallingIdentity(ident); 31718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAll0(long[] pattern) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern[i] != 0) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 331f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn public void vibratePattern(int uid, String packageName, long[] pattern, int repeat, 3327b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int usageHint, IBinder token) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 337f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 34182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ""; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s += " " + pattern[i]; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating with pattern:" + s); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we're running in the server so we can't fail 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern == null || pattern.length == 0 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || isAll0(pattern) 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || repeat >= pattern.length || token == null) { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3577b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, pattern, repeat, usageHint, uid, packageName); 35818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 35918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 36018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 36118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 36218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 36518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott removeVibrationLocked(token); 36618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 36718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat >= 0) { 36818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.addFirst(vib); 36918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 37018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 37118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // A negative repeat means that this pattern is not meant 37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // to repeat. Treat it like a simple vibration. 37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(vib); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 3843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 3853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 3863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.addLast(new VibratorService.VibrationInfo(vib.mTimeout, vib.mStartTime, 3883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski vib.mPattern, vib.mRepeat, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 3893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 39182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 39218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 40018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration vib = removeVibrationLocked(token); 40218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib == mCurrentVibration) { 40382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 40482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Canceling vibration."); 40582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 40618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 40718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 40818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 40918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 415f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 41618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final Runnable mVibrationRunnable = new Runnable() { 41782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 41818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 41918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 42018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 42118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 42218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 42718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 42818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 42918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mThread) { 43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.mDone = true; 43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.notify(); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.removeCallbacks(mVibrationRunnable); 437a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 44118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startNextVibrationLocked() { 44218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mVibrations.size() <= 0) { 443a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 444b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson mCurrentVibration = null; 44518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 44618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4474357e528208c301ccf733b074eb9a815997447c9Julia Reynolds startVibrationLocked(mVibrations.getFirst()); 44818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 45118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 452a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 4537b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (mLowPowerMode 45489c3b29a9bfa0ae9858b913bc1ab6604c4613a15Jean-Michel Trivi && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 455664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi return; 456664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 45713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4582d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE && 4592d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger !shouldVibrateForRingtone()) { 460d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds return; 461d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds } 462d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds 4631af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 4647b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock vib.mUsageHint, vib.mUid, vib.mOpPkg); 4651af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mode == AppOpsManager.MODE_ALLOWED) { 4661af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 4678fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 4681af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 4694357e528208c301ccf733b074eb9a815997447c9Julia Reynolds if (mode == AppOpsManager.MODE_ALLOWED) { 4704357e528208c301ccf733b074eb9a815997447c9Julia Reynolds mCurrentVibration = vib; 4714357e528208c301ccf733b074eb9a815997447c9Julia Reynolds } else { 472a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode == AppOpsManager.MODE_ERRORED) { 473a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 474a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 475a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mH.post(mVibrationRunnable); 476a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 477a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 478a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 479a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 48018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mTimeout != 0) { 4817b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint); 48218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.postDelayed(mVibrationRunnable, vib.mTimeout); 48318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 48418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 48518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 48618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = new VibrateThread(vib); 48718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 48818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 48918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 49018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 4912d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger private boolean shouldVibrateForRingtone() { 4922d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 493dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger int ringerMode = audioManager.getRingerModeInternal(); 4942d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger // "Also vibrate for calls" Setting in Sound 4952d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (Settings.System.getInt( 4962d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 4972d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode != AudioManager.RINGER_MODE_SILENT; 4982d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } else { 4992d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 5002d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5012d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5022d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger 503a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 504a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 505a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 506e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 507e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 5088fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 509a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 510a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 511a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 512a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 513a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 514a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 51518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 51618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration removeVibrationLocked(IBinder token) { 51718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott ListIterator<Vibration> iter = mVibrations.listIterator(0); 51818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott while (iter.hasNext()) { 51918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott Vibration vib = iter.next(); 52018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mToken == token) { 52118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott iter.remove(); 522b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(vib); 52318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return vib; 52418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 52518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 52618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // We might be looking for a simple vibration which is only stored in 52718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mCurrentVibration. 52818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 529b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mCurrentVibration); 53018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return mCurrentVibration; 53118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 53218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return null; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 535b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 536b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson if (vib.mPattern != null) { 537b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // If Vibration object has a pattern, 538b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // the Vibration object has also been linkedToDeath. 539b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 540b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 541b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 542b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 5437f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void updateInputDeviceVibrators() { 5447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mVibrations) { 5457f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doCancelVibrateLocked(); 5467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 5488206525b242ceb012d882849c4e355223ba81b9dJeff Brown mVibrateInputDevicesSetting = false; 5498206525b242ceb012d882849c4e355223ba81b9dJeff Brown try { 550d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mVibrateInputDevicesSetting = Settings.System.getIntForUser( 551d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.getContentResolver(), 552d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 5538206525b242ceb012d882849c4e355223ba81b9dJeff Brown } catch (SettingNotFoundException snfe) { 5548206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5558206525b242ceb012d882849c4e355223ba81b9dJeff Brown 556eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled(); 55713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 5588206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mVibrateInputDevicesSetting) { 5598206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (!mInputDeviceListenerRegistered) { 5608206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = true; 5618206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.registerInputDeviceListener(this, mH); 5628206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5638206525b242ceb012d882849c4e355223ba81b9dJeff Brown } else { 5648206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mInputDeviceListenerRegistered) { 5658206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = false; 5668206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.unregisterInputDeviceListener(this); 5678206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5688206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 5698206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.clear(); 5717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (mVibrateInputDevicesSetting) { 5727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown int[] ids = mIm.getInputDeviceIds(); 5737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < ids.length; i++) { 5747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown InputDevice device = mIm.getInputDevice(ids[i]); 5757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Vibrator vibrator = device.getVibrator(); 5767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibrator.hasVibrator()) { 5777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.add(vibrator); 5787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown startNextVibrationLocked(); 5847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 5897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 5947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5987f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 5997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 6007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6017f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 6031064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 6041064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 6051064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 6061064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 6071064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 6081064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 6091064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 6101064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 611c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6147b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private void doVibratorOn(long millis, int uid, int usageHint) { 6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 61682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 61782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator on for " + millis + " ms."); 61882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 619a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 620a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOn(uid, millis); 621a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = uid; 622a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 623a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6267b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint) 6277b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .build(); 6287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6297b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 6337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 6387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 63982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 64082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 64182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 642a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurVibUid >= 0) { 643a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 644a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOff(mCurVibUid); 645a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 646a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 647a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = -1; 648a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 6537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 6567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 66118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration mVibration; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mDone; 663f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 66418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott VibrateThread(Vibration vib) { 66518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibration = vib; 6667e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mTmpWorkSource.set(vib.mUid); 6677e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void delay(long duration) { 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 673e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan long bedtime = duration + SystemClock.uptimeMillis(); 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(duration); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 683e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan duration = bedtime - SystemClock.uptimeMillis(); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (duration > 0); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 691a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long[] pattern = mVibration.mPattern; 692a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int len = pattern.length; 693a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int repeat = mVibration.mRepeat; 694a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int uid = mVibration.mUid; 6957b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final int usageHint = mVibration.mUsageHint; 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = 0; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mDone) { 700f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen // add off-time duration to any accumulated on-time duration 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration += pattern[index++]; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sleep until it is time to start the vibrator 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay(duration); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read on-time duration and start the vibrator 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // duration is saved for delay() at top of loop 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = pattern[index++]; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 7167b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock VibratorService.this.doVibratorOn(duration, uid, usageHint); 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 71918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat < 0) { 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 72218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott index = repeat; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = 0; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 72918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThread == this) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread = null; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 73318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (!mDone) { 73418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration finished naturally, start the next 73518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 736b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mVibration); 73718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 741969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 744969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 74718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 748969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 749969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 750969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 751969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 752969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 753969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 754969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 755969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 7568a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 7578a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 758969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // Clear all remaining vibrations. 759969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Iterator<Vibration> it = mVibrations.iterator(); 760969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown while (it.hasNext()) { 761969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Vibration vibration = it.next(); 762969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (vibration != mCurrentVibration) { 763969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown unlinkVibration(vibration); 764969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown it.remove(); 765969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 766969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 76718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 7713a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 7723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 7733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 7743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 7753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski != PackageManager.PERMISSION_GRANTED) { 7763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 7773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Permission Denial: can't dump vibrator service from from pid=" 7783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + Binder.getCallingPid() 7793a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + ", uid=" + Binder.getCallingUid()); 7803a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return; 7813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 7833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski synchronized (mVibrations) { 7843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 7853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 7863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 7873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 7893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 790a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 791a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 792a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 793a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String[] args, ShellCallback callback, ResultReceiver resultReceiver) 794a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throws RemoteException { 795a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 796a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 797a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 798a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final class VibratorShellCommand extends ShellCommand { 799a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 800a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private static final long MAX_VIBRATION_MS = 200; 801a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 802a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final IBinder mToken; 803a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 804a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private VibratorShellCommand(IBinder token) { 805a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken = token; 806a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 807a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 808a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 809a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public int onCommand(String cmd) { 810a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if ("vibrate".equals(cmd)) { 811a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return runVibrate(); 812a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 813a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return handleDefaultCommands(cmd); 814a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 815a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 816a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private int runVibrate() { 817a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme final long duration = Long.parseLong(getNextArgRequired()); 818a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (duration > MAX_VIBRATION_MS) { 819a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS); 820a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 821a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String description = getNextArg(); 822a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (description == null) { 823a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme description = "Shell command"; 824a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 825a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme vibrate(Binder.getCallingUid(), description, duration, AudioAttributes.USAGE_UNKNOWN, 826a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken); 827a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return 0; 828a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 829a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 830a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 831a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onHelp() { 832a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme try (PrintWriter pw = getOutPrintWriter();) { 833a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println("Vibrator commands:"); 834a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" help"); 835a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Prints this help text."); 836a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 837a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" vibrate duration [description]"); 838a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Vibrates for duration milliseconds."); 839a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 840a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 841a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 842a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 843a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 845