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;
515e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Lemeimport android.util.DebugUtils;
528a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
537f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice;
547b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
56a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
57a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats;
58fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
59455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType;
60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor;
623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter;
637f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList;
6418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList;
6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
667f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub
677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        implements InputManager.InputDeviceListener {
683a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static final String TAG = "VibratorService";
6982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    private static final boolean DEBUG = false;
7018f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi    private static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
71cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood
723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final LinkedList<VibrationInfo> mPreviousVibrations;
733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final int mPreviousVibrationsLimit;
74319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman    private final boolean mAllowPriorityVibrationsInLowPowerMode;
757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final boolean mSupportsAmplitudeControl;
767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final int mDefaultVibrationAmplitude;
777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final VibrationEffect[] mFallbackEffects;
787e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    private final WorkSource mTmpWorkSource = new WorkSource();
797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Handler mH = new Handler();
807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Object mLock = new Object();
817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Context mContext;
837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final PowerManager.WakeLock mWakeLock;
84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IBatteryStats mBatteryStatsService;
86eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private InputManager mIm;
887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private volatile VibrateThread mThread;
907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // mInputDeviceVibrators lock should be acquired after mLock, if both are
927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // to be acquired
937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private Vibration mCurrentVibration;
98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int mCurVibUid = -1;
9913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private boolean mLowPowerMode;
10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private SettingsObserver mSettingObserver;
101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
1027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static boolean vibratorExists();
103e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker    native static void vibratorInit();
1047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOn(long milliseconds);
1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOff();
1067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static boolean vibratorSupportsAmplitudeControl();
1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static void vibratorSetAmplitude(int amplitude);
1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static long vibratorPerformEffect(long effect, long strength);
10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private class Vibration implements IBinder.DeathRecipient {
11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final IBinder mToken;
1127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private Vibration(IBinder token, VibrationEffect effect,
1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int usageHint, int uid, String opPkg) {
12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mToken = token;
1217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mStartTime = SystemClock.uptimeMillis();
1237b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            mUsageHint = usageHint;
1247e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mUid = uid;
1258fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer            mOpPkg = opPkg;
12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void binderDied() {
1297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (this == mCurrentVibration) {
13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public boolean hasLongerTimeout(long millis) {
1377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // If the current effect is a one shot vibration that will end after the given timeout
1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // for the new one shot vibration, then just let the current vibration finish. All
1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // other effect types will get pre-empted.
1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.OneShot) {
1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect;
1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis;
14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
1447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
146969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown
147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        public boolean isSystemHapticFeedback() {
1487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean repeating = false;
1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.Waveform) {
1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect;
1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                repeating = (waveform.getRepeatIndex() < 0);
1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
15318f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi            return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg))
1547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && !repeating;
155969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        }
15618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private static class VibrationInfo {
1597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public VibrationInfo(long startTime, VibrationEffect effect,
1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                int usageHint, int uid, String opPkg) {
1677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mStartTime = startTime;
1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mOpPkg = opPkg;
1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        @Override
1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        public String toString() {
1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            return new StringBuilder()
1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", startTime: ")
1787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mStartTime)
1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(", effect: ")
1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mEffect)
1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", usageHint: ")
1827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUsageHint)
1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", uid: ")
1847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUid)
1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", opPkg: ")
1867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mOpPkg)
1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .toString();
1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1913a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    VibratorService(Context context) {
192e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker        vibratorInit();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Reset the hardware to a default state, in case this is a runtime
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // restart instead of a fresh boot.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        vibratorOff();
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
2017e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(true);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mAppOpsService =
2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
20691268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn                BatteryStats.SERVICE_NAME));
208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
2093a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrationsLimit = mContext.getResources().getInteger(
2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                com.android.internal.R.integer.config_previousVibrationsDumpLimit);
2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
2127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mDefaultVibrationAmplitude = mContext.getResources().getInteger(
2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.integer.config_defaultVibrationAmplitude);
2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
215319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
216319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman                com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
217319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman
2183a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrations = new LinkedList<>();
21918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_SCREEN_OFF);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        context.registerReceiver(mIntentReceiver, filter);
2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] clickEffectTimings = getLongIntArray(context.getResources(),
2257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.array.config_virtualKeyVibePattern);
22657d94d9fb1e55345307e579977138aaf6177e388Michael Wright        VibrationEffect clickEffect = createEffect(clickEffectTimings);
2277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
2287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                new long[] {0, 30, 100, 30} /*timings*/, -1);
22957d94d9fb1e55345307e579977138aaf6177e388Michael Wright        long[] tickEffectTimings = getLongIntArray(context.getResources(),
23057d94d9fb1e55345307e579977138aaf6177e388Michael Wright                com.android.internal.R.array.config_clockTickVibePattern);
23157d94d9fb1e55345307e579977138aaf6177e388Michael Wright        VibrationEffect tickEffect = createEffect(tickEffectTimings);
23257d94d9fb1e55345307e579977138aaf6177e388Michael Wright
23357d94d9fb1e55345307e579977138aaf6177e388Michael Wright        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect };
23457d94d9fb1e55345307e579977138aaf6177e388Michael Wright    }
2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
23657d94d9fb1e55345307e579977138aaf6177e388Michael Wright    private static VibrationEffect createEffect(long[] timings) {
23757d94d9fb1e55345307e579977138aaf6177e388Michael Wright        if (timings == null || timings.length == 0) {
23857d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return null;
23957d94d9fb1e55345307e579977138aaf6177e388Michael Wright        } else if (timings.length == 1) {
24057d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE);
24157d94d9fb1e55345307e579977138aaf6177e388Michael Wright        } else {
24257d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return VibrationEffect.createWaveform(timings, -1);
24357d94d9fb1e55345307e579977138aaf6177e388Michael Wright        }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
2478ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa        mIm = mContext.getSystemService(InputManager.class);
24813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
249d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
250eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
251eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
252eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
253455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
254455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public int getServiceType() {
255455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                        return ServiceType.VIBRATION;
256455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
257455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei
258455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
259455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public void onLowPowerModeChanged(PowerSaveState result) {
2607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        updateVibrators();
261455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
262eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
263eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
2647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
26613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
26713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
268d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
269d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
270d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
2717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                updateVibrators();
272d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
273d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
274d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
2757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
2767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
2777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
27813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
28113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
28213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
28413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
2857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            updateVibrators();
28613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
28713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
28813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
290ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
292ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    @Override // Binder call
2957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public boolean hasAmplitudeControl() {
2967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
2977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input device vibrators don't support amplitude controls yet, but are still used over
2987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // the system vibrator when connected.
2997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty();
3007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
3027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
306f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
307f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
308f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
309f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
310f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
311f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
312f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
313f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    /**
3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * Validate the incoming VibrationEffect.
3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * We can't throw exceptions here since we might be called from some system_server component,
3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * which would bring the whole system down.
3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * @return whether the VibrationEffect is valid
3217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     */
3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static boolean verifyVibrationEffect(VibrationEffect effect) {
3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect == null) {
3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Effect must not be null.
3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "effect must not be null");
3267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
328a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            effect.validate();
3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (Exception e) {
3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e);
3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
33318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
3347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return true;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static long[] getLongIntArray(Resources r, int resid) {
3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int[] ar = r.getIntArray(resid);
3397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (ar == null) {
3407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return null;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] out = new long[ar.length];
3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        for (int i = 0; i < ar.length; i++) {
3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            out[i] = ar[i];
3457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return out;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IBinder token) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (token == null) {
3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "token must not be null");
3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
360f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (!verifyVibrationEffect(effect)) {
3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // If our current vibration is longer than the new vibration and is the same amplitude,
3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // then just let the current one finish.
3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.OneShot
3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration != null
3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
3717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot currentOneShot =
3727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    (VibrationEffect.OneShot) mCurrentVibration.mEffect;
3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
3757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
37658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright                    Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration");
3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
38258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        // If the current vibration is repeating and the incoming one is non-repeating, then ignore
38358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        // the non-repeating vibration. This is so that we don't cancel vibrations that are meant
38458c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        // to grab the attention of the user, like ringtones and alarms, in favor of one-shot
38558c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        // vibrations that are likely quite short.
38658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        if (!isRepeatingVibration(effect)
38758c4631c29b4f36737f261d1a2888e66592eda32Michael Wright                && mCurrentVibration != null && isRepeatingVibration(mCurrentVibration.mEffect)) {
38858c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            if (DEBUG) {
38958c4631c29b4f36737f261d1a2888e66592eda32Michael Wright                Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
39058c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            }
39158c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            return;
39258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        }
39358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright
3947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // Only link against waveforms since they potentially don't have a finish if
3977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // they're repeating. Let other effects just play out until they're done.
3987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
39918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
40018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
40218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
40318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
4077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long ident = Binder.clearCallingIdentity();
4087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
4097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
41018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
4117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                startVibrationLocked(vib);
4123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                addToPreviousVibrationsLocked(vib);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } finally {
4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Binder.restoreCallingIdentity(ident);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41958c4631c29b4f36737f261d1a2888e66592eda32Michael Wright    private static boolean isRepeatingVibration(VibrationEffect effect) {
42058c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
42158c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            final VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
42258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            if (waveform.getRepeatIndex() >= 0) {
42358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright                return true;
42458c4631c29b4f36737f261d1a2888e66592eda32Michael Wright            }
42558c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        }
42658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright        return false;
42758c4631c29b4f36737f261d1a2888e66592eda32Michael Wright    }
42858c4631c29b4f36737f261d1a2888e66592eda32Michael Wright
4293a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private void addToPreviousVibrationsLocked(Vibration vib) {
4303a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
4313a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            mPreviousVibrations.removeFirst();
4323a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
4337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mPreviousVibrations.addLast(new VibrationInfo(
4347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
4353a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
4363a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
43782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.d(TAG, "Canceling vibration.");
4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long ident = Binder.clearCallingIdentity();
4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                try {
45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } finally {
4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Binder.restoreCallingIdentity(ident);
45318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
45418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
457f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Runnable mVibrationEndRunnable = new Runnable() {
45982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown        @Override
46018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            onVibrationFinished();
46218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
46318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
46418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
46518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mH.removeCallbacks(mVibrationEndRunnable);
46718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread.cancel();
46918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
472a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
47318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
47418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // Callback for whenever the current vibration has finished played out
4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void onVibrationFinished() {
4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (DEBUG) {
4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Vibration finished, cleaning up");
4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Make sure the vibration is really done. This also reports that the vibration is
4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // finished.
4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doCancelVibrateLocked();
48418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
48518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
48618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
48718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
488319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        if (!isAllowedToVibrate(vib)) {
4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, low power mode");
491664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
49413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                !shouldVibrateForRingtone()) {
4977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
499d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds            }
5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
502d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds
5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        final int mode = getAppOpMode(vib);
5047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mode != AppOpsManager.MODE_ALLOWED) {
5057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ERRORED) {
5067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // We might be getting calls from within system_server, so we don't actually want
5077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // to throw a SecurityException here.
5087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
5091af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
5107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
511a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
5127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        startVibrationInnerLocked(vib);
5137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
5157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void startVibrationInnerLocked(Vibration vib) {
5167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mCurrentVibration = vib;
5177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.OneShot) {
5187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());
5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Waveform) {
52218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
52318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
52618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timeout = doVibratorPrebakedEffectLocked(vib);
5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (timeout > 0) {
5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mH.postDelayed(mVibrationEndRunnable, timeout);
5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Unknown vibration type, ignoring");
53418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
53518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
53618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
537319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman    private boolean isAllowedToVibrate(Vibration vib) {
538319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        if (!mLowPowerMode) {
539319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            return true;
540319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        }
541319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
542319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            return true;
543319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        }
544319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        if (!mAllowPriorityVibrationsInLowPowerMode) {
545319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            return false;
546319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        }
547319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        if (vib.mUsageHint == AudioAttributes.USAGE_ALARM ||
548319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
549319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
550319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman
551319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman            return true;
552319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        }
553319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman
554319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman        return false;
555319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman    }
556319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman
5572d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    private boolean shouldVibrateForRingtone() {
5582d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
559dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger        int ringerMode = audioManager.getRingerModeInternal();
5602d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        // "Also vibrate for calls" Setting in Sound
5612d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        if (Settings.System.getInt(
5622d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger                mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
5632d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode != AudioManager.RINGER_MODE_SILENT;
5642d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        } else {
5652d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
5662d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        }
5672d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    }
5682d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger
5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private int getAppOpMode(Vibration vib) {
5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int mode;
5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ALLOWED) {
5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Failed to get appop mode for vibration!", e);
5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = AppOpsManager.MODE_IGNORED;
5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return mode;
5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
585a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
586a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
587a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
588e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
589e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
5908fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
592a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
593a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
594a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
595a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
596b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.Waveform) {
598b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
599b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
600b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
601b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void updateVibrators() {
6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
6047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
6067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (devicesUpdated || lowPowerModeUpdated) {
6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // If the state changes out from under us then just reset.
6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doCancelVibrateLocked();
6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
6117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6138206525b242ceb012d882849c4e355223ba81b9dJeff Brown
6147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateInputDeviceVibratorsLocked() {
6157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean changed = false;
6167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean vibrateInputDevices = false;
6177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
6187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrateInputDevices = Settings.System.getIntForUser(
6197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mContext.getContentResolver(),
6207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
6217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (SettingNotFoundException snfe) {
6227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vibrateInputDevices != mVibrateInputDevicesSetting) {
6247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            changed = true;
6257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mVibrateInputDevicesSetting = vibrateInputDevices;
6267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
62713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
6287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
6297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (!mInputDeviceListenerRegistered) {
6307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = true;
6317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.registerInputDeviceListener(this, mH);
6327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
6337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
6347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mInputDeviceListenerRegistered) {
6357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = false;
6367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.unregisterInputDeviceListener(this);
6377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
6387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6398206525b242ceb012d882849c4e355223ba81b9dJeff Brown
6407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mInputDeviceVibrators.clear();
6417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int[] ids = mIm.getInputDeviceIds();
6437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            for (int i = 0; i < ids.length; i++) {
6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                InputDevice device = mIm.getInputDevice(ids[i]);
6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Vibrator vibrator = device.getVibrator();
6467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (vibrator.hasVibrator()) {
6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mInputDeviceVibrators.add(vibrator);
6487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return changed;
6537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateLowPowerModeLocked() {
6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean lowPowerMode = mPowerManagerInternal
6577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
6587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (lowPowerMode != mLowPowerMode) {
6597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mLowPowerMode = lowPowerMode;
6607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return false;
6637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
6677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
6777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
6811064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
6821064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
6831064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
6841064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
6851064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
6861064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
6871064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
6881064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
689c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
6937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                amplitude = mDefaultVibrationAmplitude;
69682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.d(TAG, "Turning vibrator on for " + millis + " ms" +
6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        " with amplitude " + amplitude + ".");
700a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOnLocked(uid, millis);
7027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
7037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final AudioAttributes attributes =
7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        new AudioAttributes.Builder().setUsage(usageHint).build();
7067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
7077b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
7087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
7097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // Note: ordering is important here! Many haptic drivers will reset their amplitude
7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // when enabled, so we always have to enable frst, then set the amplitude.
7127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doVibratorSetAmplitude(amplitude);
7147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
7157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
7167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
7177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorSetAmplitude(int amplitude) {
7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mSupportsAmplitudeControl) {
7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibratorSetAmplitude(amplitude);
7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
7257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
72682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            if (DEBUG) {
72782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown                Slog.d(TAG, "Turning vibrator off.");
72882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOffLocked();
7307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
7317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
7327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
7337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
7347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
7357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
7367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
7377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
7387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
7397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
7407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private long doVibratorPrebakedEffectLocked(Vibration vib) {
7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input devices don't support prebaked effect, so skip trying it with them.
7457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int vibratorCount = mInputDeviceVibrators.size();
7467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (vibratorCount == 0) {
7477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
7487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (timeout > 0) {
7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    noteVibratorOnLocked(vib.mUid, timeout);
7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return timeout;
7517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
753dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright            if (!prebaked.shouldFallback()) {
754dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright                return 0;
755dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright            }
7567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int id = prebaked.getId();
757017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer            if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) {
7587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Failed to play prebaked effect, no fallback");
7597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return 0;
7607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect = mFallbackEffects[id];
7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Vibration fallbackVib =
7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            startVibrationInnerLocked(fallbackVib);
7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return 0;
7677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOnLocked(int uid, long millis) {
7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mBatteryStatsService.noteVibratorOn(uid, millis);
7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = uid;
7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOffLocked() {
7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mCurVibUid >= 0) {
7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mBatteryStatsService.noteVibratorOff(mCurVibUid);
7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = -1;
7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect.Waveform mWaveform;
7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
790f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private boolean mForceStop;
7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWaveform = waveform;
7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mTmpWorkSource.set(uid);
7987e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long delayLocked(long duration) {
8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long durationRemaining = duration;
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long bedtime = duration + SystemClock.uptimeMillis();
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        this.wait(durationRemaining);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    catch (InterruptedException e) { }
8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (mForceStop) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    durationRemaining = bedtime - SystemClock.uptimeMillis();
8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } while (durationRemaining > 0);
8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return duration - durationRemaining;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return 0;
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWakeLock.acquire();
8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                boolean finished = playWaveform();
8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (finished) {
8267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    onVibrationFinished();
8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } finally {
8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mWakeLock.release();
8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Play the waveform.
8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         *
8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * @return true if it finished naturally, false otherwise (e.g. it was canceled).
8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public boolean playWaveform() {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long[] timings = mWaveform.getTimings();
8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int[] amplitudes = mWaveform.getAmplitudes();
8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int len = timings.length;
8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int repeat = mWaveform.getRepeatIndex();
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int index = 0;
8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long onDuration = 0;
8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                while (!mForceStop) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final int amplitude = amplitudes[index];
8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final long duration = timings[index++];
8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (duration <= 0) {
8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            continue;
8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            if (onDuration <= 0) {
8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // Telling the vibrator to start multiple times usually causes
8577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // effects to feel "choppy" because the motor resets at every on
8587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // command.  Instead we figure out how long our next "on" period is
8597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // going to be, tell the motor to stay on for the full duration,
8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // and then wake up to change the amplitude at the appropriate
8617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // intervals.
8627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                onDuration =
8637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                        getTotalOnDuration(timings, amplitudes, index - 1, repeat);
8647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
8657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            } else {
8667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorSetAmplitude(amplitude);
8677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            }
8687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        long waitTime = delayLocked(duration);
8717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            onDuration -= waitTime;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else if (repeat < 0) {
8757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        index = repeat;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return !mForceStop;
8817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public void cancel() {
8857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (this) {
8867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.mForceStop = true;
8877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.notify();
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Get the duration the vibrator will be on starting at startIndex until the next time it's
8937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * off.
8947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long getTotalOnDuration(
8967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
8977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int i = startIndex;
8987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timing = 0;
8997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            while(amplitudes[i] != 0) {
9007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                timing += timings[i++];
9017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i >= timings.length) {
9027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (repeatIndex >= 0) {
9037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        i = repeatIndex;
9047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else {
9057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
9067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    }
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i == startIndex) {
9097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return 1000;
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return timing;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
914969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
917969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
9207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                synchronized (mLock) {
921969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
922969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
923969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
924969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
925969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
926969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
927969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
928969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
9298a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
93018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
9343a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
9353a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    @Override
9363a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
937fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
9383a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
9393a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        pw.println("Previous vibrations:");
9407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
9413a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            for (VibrationInfo info : mPreviousVibrations) {
9423a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.print("  ");
9433a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.println(info.toString());
9443a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            }
9453a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
9463a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    @Override
949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
951a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            throws RemoteException {
952a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
953a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
954a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
955a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    private final class VibratorShellCommand extends ShellCommand {
956a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
957a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private static final long MAX_VIBRATION_MS = 200;
958a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
959a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private final IBinder mToken;
960a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
961a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private VibratorShellCommand(IBinder token) {
962a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            mToken = token;
963a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
964a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
965a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
966a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public int onCommand(String cmd) {
967a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if ("vibrate".equals(cmd)) {
968a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                return runVibrate();
969a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
970a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return handleDefaultCommands(cmd);
971a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
972a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
973a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private int runVibrate() {
9745e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme            try {
9755e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                final int zenMode = Settings.Global.getInt(mContext.getContentResolver(),
9765e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                        Settings.Global.ZEN_MODE);
9775e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                if (zenMode != Settings.Global.ZEN_MODE_OFF) {
9785e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                    try (PrintWriter pw = getOutPrintWriter();) {
9795e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                        pw.print("Ignoring because device is on DND mode ");
9805e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                        pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_",
9815e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                                zenMode));
9825e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                        return 0;
9835e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                    }
9845e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                }
9855e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme            } catch (SettingNotFoundException e) {
9865e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                // ignore
9875e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme            }
9885e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme
989a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            final long duration = Long.parseLong(getNextArgRequired());
990a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (duration > MAX_VIBRATION_MS) {
991a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
992a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
993a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String description = getNextArg();
994a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (description == null) {
995a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                description = "Shell command";
996a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
9977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
9987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect =
9997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
10007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
1001a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                    mToken);
1002a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return 0;
1003a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
1004a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
1005a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
1006a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public void onHelp() {
1007a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            try (PrintWriter pw = getOutPrintWriter();) {
1008a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("Vibrator commands:");
1009a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  help");
1010a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Prints this help text.");
1011a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
1012a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  vibrate duration [description]");
10135e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                pw.println("    Vibrates for duration milliseconds; ignored when device is on DND ");
10145e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme                pw.println("    (Do Not Disturb) mode.");
1015a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
1016a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
1017a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
1018a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
1019a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1021