VibratorService.java revision b97ae357cad31913793f2695123c7f09cf5eaddf
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;
257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.content.res.Resources;
267f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.database.ContentObserver;
277f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.hardware.input.InputManager;
287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.hardware.vibrator.V1_0.Constants.EffectStrength;
292d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebingerimport android.media.AudioManager;
30455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport android.os.PowerSaveState;
3191268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats;
3295e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler;
333a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
35eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
38a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ResultReceiver;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager;
42a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCallback;
43a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCommand;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
45d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle;
467f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator;
477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.os.VibrationEffect;
487e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
497f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings;
507f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException;
518a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
527f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice;
537b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
56a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats;
57fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
58455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType;
59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor;
613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter;
627f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList;
633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays;
64969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator;
6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList;
6618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator;
6718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
687f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub
697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        implements InputManager.InputDeviceListener {
703a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static final String TAG = "VibratorService";
7182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    private static final boolean DEBUG = false;
7218f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi    private static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
73cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood
743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final LinkedList<VibrationInfo> mPreviousVibrations;
753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final int mPreviousVibrationsLimit;
767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final boolean mSupportsAmplitudeControl;
777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final int mDefaultVibrationAmplitude;
787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final VibrationEffect[] mFallbackEffects;
797e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    private final WorkSource mTmpWorkSource = new WorkSource();
807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Handler mH = new Handler();
817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Object mLock = new Object();
827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Context mContext;
847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final PowerManager.WakeLock mWakeLock;
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IBatteryStats mBatteryStatsService;
87eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private InputManager mIm;
897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private volatile VibrateThread mThread;
917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // mInputDeviceVibrators lock should be acquired after mLock, if both are
937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // to be acquired
947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private Vibration mCurrentVibration;
99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int mCurVibUid = -1;
10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private boolean mLowPowerMode;
10113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private SettingsObserver mSettingObserver;
102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
1037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static boolean vibratorExists();
104e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker    native static void vibratorInit();
1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOn(long milliseconds);
1067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOff();
1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static boolean vibratorSupportsAmplitudeControl();
1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static void vibratorSetAmplitude(int amplitude);
1097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static long vibratorPerformEffect(long effect, long strength);
11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private class Vibration implements IBinder.DeathRecipient {
11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final IBinder mToken;
1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private Vibration(IBinder token, VibrationEffect effect,
1207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int usageHint, int uid, String opPkg) {
12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mToken = token;
1227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mStartTime = SystemClock.uptimeMillis();
1247b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            mUsageHint = usageHint;
1257e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mUid = uid;
1268fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer            mOpPkg = opPkg;
12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void binderDied() {
1307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (this == mCurrentVibration) {
13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public boolean hasLongerTimeout(long millis) {
1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // If the current effect is a one shot vibration that will end after the given timeout
1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // for the new one shot vibration, then just let the current vibration finish. All
1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // other effect types will get pre-empted.
1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.OneShot) {
1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect;
1437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis;
14418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
1457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown
148969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        public boolean isSystemHapticFeedback() {
1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean repeating = false;
1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.Waveform) {
1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect;
1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                repeating = (waveform.getRepeatIndex() < 0);
1537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
15418f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi            return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg))
1557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && !repeating;
156969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        }
15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
15818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private static class VibrationInfo {
1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public VibrationInfo(long startTime, VibrationEffect effect,
1673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                int usageHint, int uid, String opPkg) {
1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mStartTime = startTime;
1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
1727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mOpPkg = opPkg;
1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        @Override
1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        public String toString() {
1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            return new StringBuilder()
1783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", startTime: ")
1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mStartTime)
1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(", effect: ")
1817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mEffect)
1823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", usageHint: ")
1837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUsageHint)
1843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", uid: ")
1857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUid)
1863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", opPkg: ")
1877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mOpPkg)
1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .toString();
1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
1913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1923a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    VibratorService(Context context) {
193e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker        vibratorInit();
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Reset the hardware to a default state, in case this is a runtime
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // restart instead of a fresh boot.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        vibratorOff();
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
1997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
2027e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(true);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mAppOpsService =
2067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
20891268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn                BatteryStats.SERVICE_NAME));
209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrationsLimit = mContext.getResources().getInteger(
2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                com.android.internal.R.integer.config_previousVibrationsDumpLimit);
2123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mDefaultVibrationAmplitude = mContext.getResources().getInteger(
2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.integer.config_defaultVibrationAmplitude);
2157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2163a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrations = new LinkedList<>();
21718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_SCREEN_OFF);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        context.registerReceiver(mIntentReceiver, filter);
2217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] clickEffectTimings = getLongIntArray(context.getResources(),
2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.array.config_virtualKeyVibePattern);
224b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        VibrationEffect clickEffect;
225b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        if (clickEffectTimings.length == 1) {
226b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer            clickEffect = VibrationEffect.createOneShot(
227b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer                    clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE);
228b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        } else {
229b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer            clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
230b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        }
2317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
2327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                new long[] {0, 30, 100, 30} /*timings*/, -1);
2337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
2398ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa        mIm = mContext.getSystemService(InputManager.class);
24013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
241d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
242eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
243eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
244eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
245455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public int getServiceType() {
247455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                        return ServiceType.VIBRATION;
248455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
249455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei
250455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
251455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public void onLowPowerModeChanged(PowerSaveState result) {
2527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        updateVibrators();
253455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
254eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
255eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
2567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
25713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
260d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
261d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
262d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
2637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                updateVibrators();
264d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
265d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
266d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
2677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
2687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
2697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
27013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
27413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
27513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
27613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
2777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            updateVibrators();
27813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
282ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
284ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    @Override // Binder call
2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public boolean hasAmplitudeControl() {
2887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
2897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input device vibrators don't support amplitude controls yet, but are still used over
2907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // the system vibrator when connected.
2917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty();
2927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
2937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
295f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
299f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
300f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
301f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
302f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
3067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    /**
3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * Validate the incoming VibrationEffect.
3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * We can't throw exceptions here since we might be called from some system_server component,
3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * which would bring the whole system down.
3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * @return whether the VibrationEffect is valid
3137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     */
3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static boolean verifyVibrationEffect(VibrationEffect effect) {
3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect == null) {
3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Effect must not be null.
3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "effect must not be null");
3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
320a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            effect.validate();
3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (Exception e) {
3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e);
3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
32518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
3267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return true;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static long[] getLongIntArray(Resources r, int resid) {
3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int[] ar = r.getIntArray(resid);
3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (ar == null) {
3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return null;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] out = new long[ar.length];
3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        for (int i = 0; i < ar.length; i++) {
3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            out[i] = ar[i];
3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return out;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IBinder token) {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (token == null) {
3497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "token must not be null");
3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
352f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
3537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (!verifyVibrationEffect(effect)) {
3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // If our current vibration is longer than the new vibration and is the same amplitude,
3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // then just let the current one finish.
3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.OneShot
3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration != null
3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot currentOneShot =
3647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    (VibrationEffect.OneShot) mCurrentVibration.mEffect;
3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // Only link against waveforms since they potentially don't have a finish if
3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // they're repeating. Let other effects just play out until they're done.
3787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
37918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
38218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
3847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long ident = Binder.clearCallingIdentity();
3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
3897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
39018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
3917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                startVibrationLocked(vib);
3923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                addToPreviousVibrationsLocked(vib);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } finally {
3957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Binder.restoreCallingIdentity(ident);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private void addToPreviousVibrationsLocked(Vibration vib) {
4003a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
4013a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            mPreviousVibrations.removeFirst();
4023a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
4037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mPreviousVibrations.addLast(new VibrationInfo(
4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
4053a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
4063a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
40782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
40818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
4167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.d(TAG, "Canceling vibration.");
4177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
4187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long ident = Binder.clearCallingIdentity();
4197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                try {
42018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
4217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } finally {
4227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Binder.restoreCallingIdentity(ident);
42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
427f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
4287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Runnable mVibrationEndRunnable = new Runnable() {
42982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown        @Override
43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
4317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            onVibrationFinished();
43218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
4367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mH.removeCallbacks(mVibrationEndRunnable);
43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
4387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread.cancel();
43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
442a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
44318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // Callback for whenever the current vibration has finished played out
4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void onVibrationFinished() {
4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (DEBUG) {
4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Vibration finished, cleaning up");
4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Make sure the vibration is really done. This also reports that the vibration is
4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // finished.
4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doCancelVibrateLocked();
45418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
45518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
45618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
45718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, low power mode");
461664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
4627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
46413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                !shouldVibrateForRingtone()) {
4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
469d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds            }
4707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
472d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds
4737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        final int mode = getAppOpMode(vib);
4747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mode != AppOpsManager.MODE_ALLOWED) {
4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ERRORED) {
4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // We might be getting calls from within system_server, so we don't actually want
4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // to throw a SecurityException here.
4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
4791af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
481a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        startVibrationInnerLocked(vib);
4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
4857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void startVibrationInnerLocked(Vibration vib) {
4867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mCurrentVibration = vib;
4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.OneShot) {
4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());
4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Waveform) {
49218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
49318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
4947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
49618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
4977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timeout = doVibratorPrebakedEffectLocked(vib);
4997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (timeout > 0) {
5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mH.postDelayed(mVibrationEndRunnable, timeout);
5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Unknown vibration type, ignoring");
50418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
50518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
50618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
5072d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    private boolean shouldVibrateForRingtone() {
5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
509dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger        int ringerMode = audioManager.getRingerModeInternal();
5102d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        // "Also vibrate for calls" Setting in Sound
5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        if (Settings.System.getInt(
5122d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger                mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
5132d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode != AudioManager.RINGER_MODE_SILENT;
5142d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        } else {
5152d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
5162d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        }
5172d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    }
5182d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger
5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private int getAppOpMode(Vibration vib) {
5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int mode;
5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ALLOWED) {
5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Failed to get appop mode for vibration!", e);
5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = AppOpsManager.MODE_IGNORED;
5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return mode;
5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
538e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
5408fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
5417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
546b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
5477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.Waveform) {
548b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
549b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
550b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
551b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
5527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void updateVibrators() {
5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
5567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (devicesUpdated || lowPowerModeUpdated) {
5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // If the state changes out from under us then just reset.
5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doCancelVibrateLocked();
5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5638206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateInputDeviceVibratorsLocked() {
5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean changed = false;
5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean vibrateInputDevices = false;
5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrateInputDevices = Settings.System.getIntForUser(
5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mContext.getContentResolver(),
5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (SettingNotFoundException snfe) {
5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vibrateInputDevices != mVibrateInputDevicesSetting) {
5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            changed = true;
5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mVibrateInputDevicesSetting = vibrateInputDevices;
5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
57713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (!mInputDeviceListenerRegistered) {
5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = true;
5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.registerInputDeviceListener(this, mH);
5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mInputDeviceListenerRegistered) {
5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = false;
5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.unregisterInputDeviceListener(this);
5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5898206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mInputDeviceVibrators.clear();
5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int[] ids = mIm.getInputDeviceIds();
5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            for (int i = 0; i < ids.length; i++) {
5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                InputDevice device = mIm.getInputDevice(ids[i]);
5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Vibrator vibrator = device.getVibrator();
5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (vibrator.hasVibrator()) {
5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mInputDeviceVibrators.add(vibrator);
5987f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
5997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return changed;
6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateLowPowerModeLocked() {
6067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean lowPowerMode = mPowerManagerInternal
6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (lowPowerMode != mLowPowerMode) {
6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mLowPowerMode = lowPowerMode;
6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return false;
6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
6177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
6227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
6277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
6311064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
6321064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
6331064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
6341064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
6351064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
6361064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
6371064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
6381064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
639c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
6407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
6437f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                amplitude = mDefaultVibrationAmplitude;
64682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.d(TAG, "Turning vibrator on for " + millis + " ms" +
6497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        " with amplitude " + amplitude + ".");
650a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
6517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOnLocked(uid, millis);
6527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final AudioAttributes attributes =
6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        new AudioAttributes.Builder().setUsage(usageHint).build();
6567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6577b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // Note: ordering is important here! Many haptic drivers will reset their amplitude
6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // when enabled, so we always have to enable frst, then set the amplitude.
6627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
6637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doVibratorSetAmplitude(amplitude);
6647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorSetAmplitude(int amplitude) {
6697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mSupportsAmplitudeControl) {
6707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibratorSetAmplitude(amplitude);
6717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
67682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            if (DEBUG) {
67782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown                Slog.d(TAG, "Turning vibrator off.");
67882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOffLocked();
6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
6847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
6877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private long doVibratorPrebakedEffectLocked(Vibration vib) {
6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input devices don't support prebaked effect, so skip trying it with them.
6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int vibratorCount = mInputDeviceVibrators.size();
6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (vibratorCount == 0) {
6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (timeout > 0) {
6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    noteVibratorOnLocked(vib.mUid, timeout);
7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return timeout;
7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int id = prebaked.getId();
7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (id < 0 || id >= mFallbackEffects.length) {
7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Failed to play prebaked effect, no fallback");
7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return 0;
7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect = mFallbackEffects[id];
7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Vibration fallbackVib =
7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            startVibrationInnerLocked(fallbackVib);
7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return 0;
7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOnLocked(int uid, long millis) {
7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mBatteryStatsService.noteVibratorOn(uid, millis);
7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = uid;
7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOffLocked() {
7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mCurVibUid >= 0) {
7267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mBatteryStatsService.noteVibratorOff(mCurVibUid);
7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = -1;
7307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
7347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect.Waveform mWaveform;
7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
737f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
7387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private boolean mForceStop;
7397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWaveform = waveform;
7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mTmpWorkSource.set(uid);
7457e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long delayLocked(long duration) {
7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long durationRemaining = duration;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
7517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long bedtime = duration + SystemClock.uptimeMillis();
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
7547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        this.wait(durationRemaining);
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    catch (InterruptedException e) { }
7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (mForceStop) {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    durationRemaining = bedtime - SystemClock.uptimeMillis();
7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } while (durationRemaining > 0);
7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return duration - durationRemaining;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return 0;
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWakeLock.acquire();
7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                boolean finished = playWaveform();
7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (finished) {
7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    onVibrationFinished();
7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } finally {
7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mWakeLock.release();
7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Play the waveform.
7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         *
7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * @return true if it finished naturally, false otherwise (e.g. it was canceled).
7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public boolean playWaveform() {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long[] timings = mWaveform.getTimings();
7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int[] amplitudes = mWaveform.getAmplitudes();
7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int len = timings.length;
7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int repeat = mWaveform.getRepeatIndex();
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int index = 0;
7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long onDuration = 0;
7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                while (!mForceStop) {
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final int amplitude = amplitudes[index];
7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final long duration = timings[index++];
7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (duration <= 0) {
7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            continue;
8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            if (onDuration <= 0) {
8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // Telling the vibrator to start multiple times usually causes
8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // effects to feel "choppy" because the motor resets at every on
8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // command.  Instead we figure out how long our next "on" period is
8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // going to be, tell the motor to stay on for the full duration,
8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // and then wake up to change the amplitude at the appropriate
8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // intervals.
8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                onDuration =
8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                        getTotalOnDuration(timings, amplitudes, index - 1, repeat);
8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            } else {
8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorSetAmplitude(amplitude);
8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            }
8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        long waitTime = delayLocked(duration);
8187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            onDuration -= waitTime;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else if (repeat < 0) {
8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        index = repeat;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return !mForceStop;
8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public void cancel() {
8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (this) {
8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.mForceStop = true;
8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.notify();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Get the duration the vibrator will be on starting at startIndex until the next time it's
8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * off.
8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long getTotalOnDuration(
8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int i = startIndex;
8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timing = 0;
8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            while(amplitudes[i] != 0) {
8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                timing += timings[i++];
8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i >= timings.length) {
8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (repeatIndex >= 0) {
8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        i = repeatIndex;
8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else {
8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i == startIndex) {
8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return 1000;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return timing;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
861969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
864969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
8677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                synchronized (mLock) {
868969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
869969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
870969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
871969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
872969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
873969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
874969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
875969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
8768a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
87718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
8813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    @Override
8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
884fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
8853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        pw.println("Previous vibrations:");
8877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
8883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            for (VibrationInfo info : mPreviousVibrations) {
8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.print("  ");
8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.println(info.toString());
8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            }
8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
8933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
894a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    @Override
896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            throws RemoteException {
899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    private final class VibratorShellCommand extends ShellCommand {
903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private static final long MAX_VIBRATION_MS = 200;
905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private final IBinder mToken;
907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private VibratorShellCommand(IBinder token) {
909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            mToken = token;
910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public int onCommand(String cmd) {
914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if ("vibrate".equals(cmd)) {
915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                return runVibrate();
916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return handleDefaultCommands(cmd);
918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private int runVibrate() {
921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            final long duration = Long.parseLong(getNextArgRequired());
922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (duration > MAX_VIBRATION_MS) {
923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String description = getNextArg();
926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (description == null) {
927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                description = "Shell command";
928a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
9297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect =
9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
9327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
933a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                    mToken);
934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return 0;
935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public void onHelp() {
939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            try (PrintWriter pw = getOutPrintWriter();) {
940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("Vibrator commands:");
941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  help");
942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Prints this help text.");
943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  vibrate duration [description]");
945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Vibrates for duration milliseconds.");
946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
952