• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings;
18 
19 import static android.view.HapticFeedbackConstants.CLOCK_TICK;
20 
21 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SETTINGS_SLIDER;
22 
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.database.ContentObserver;
26 import android.hardware.input.InputManager;
27 import android.os.Handler;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.provider.Settings;
31 import android.util.AttributeSet;
32 import android.view.View;
33 import android.widget.SeekBar;
34 
35 import com.android.internal.jank.InteractionJankMonitor;
36 
37 public class PointerSpeedPreference extends SeekBarDialogPreference implements
38         SeekBar.OnSeekBarChangeListener {
39     private final InputManager mIm;
40     private final InteractionJankMonitor mJankMonitor = InteractionJankMonitor.getInstance();
41     private SeekBar mSeekBar;
42 
43     private int mOldSpeed;
44     private boolean mRestoredOldState;
45 
46     private boolean mTouchInProgress;
47     private int mLastProgress = -1;
48 
49     private ContentObserver mSpeedObserver = new ContentObserver(new Handler()) {
50         @Override
51         public void onChange(boolean selfChange) {
52             onSpeedChanged();
53         }
54     };
55 
PointerSpeedPreference(Context context, AttributeSet attrs)56     public PointerSpeedPreference(Context context, AttributeSet attrs) {
57         super(context, attrs);
58         mIm = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
59     }
60 
61     @Override
onClick()62     protected void onClick() {
63         super.onClick();
64 
65         getContext().getContentResolver().registerContentObserver(
66                 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
67                 mSpeedObserver);
68 
69         mRestoredOldState = false;
70     }
71 
72     @Override
onBindDialogView(View view)73     protected void onBindDialogView(View view) {
74         super.onBindDialogView(view);
75 
76         mSeekBar = getSeekBar(view);
77         mSeekBar.setMax(InputManager.MAX_POINTER_SPEED - InputManager.MIN_POINTER_SPEED);
78         mOldSpeed = mIm.getPointerSpeed(getContext());
79         mSeekBar.setProgress(mOldSpeed - InputManager.MIN_POINTER_SPEED);
80         mSeekBar.setOnSeekBarChangeListener(this);
81         mSeekBar.setContentDescription(getTitle());
82     }
83 
onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)84     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
85         if (!mTouchInProgress) {
86             mIm.tryPointerSpeed(progress + InputManager.MIN_POINTER_SPEED);
87         }
88         if (progress != mLastProgress) {
89             seekBar.performHapticFeedback(CLOCK_TICK);
90             mLastProgress = progress;
91         }
92     }
93 
onStartTrackingTouch(SeekBar seekBar)94     public void onStartTrackingTouch(SeekBar seekBar) {
95         mTouchInProgress = true;
96         mJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
97                 .withView(CUJ_SETTINGS_SLIDER, seekBar)
98                 .setTag(getKey()));
99     }
100 
onStopTrackingTouch(SeekBar seekBar)101     public void onStopTrackingTouch(SeekBar seekBar) {
102         mTouchInProgress = false;
103         mIm.tryPointerSpeed(seekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
104         mJankMonitor.end(CUJ_SETTINGS_SLIDER);
105     }
106 
onSpeedChanged()107     private void onSpeedChanged() {
108         int speed = mIm.getPointerSpeed(getContext());
109         mSeekBar.setProgress(speed - InputManager.MIN_POINTER_SPEED);
110     }
111 
112     @Override
onDialogClosed(boolean positiveResult)113     protected void onDialogClosed(boolean positiveResult) {
114         super.onDialogClosed(positiveResult);
115 
116         final ContentResolver resolver = getContext().getContentResolver();
117 
118         if (positiveResult) {
119             mIm.setPointerSpeed(getContext(),
120                     mSeekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
121         } else {
122             restoreOldState();
123         }
124 
125         resolver.unregisterContentObserver(mSpeedObserver);
126     }
127 
restoreOldState()128     private void restoreOldState() {
129         if (mRestoredOldState) return;
130 
131         mIm.tryPointerSpeed(mOldSpeed);
132         mRestoredOldState = true;
133     }
134 
135     @Override
onSaveInstanceState()136     protected Parcelable onSaveInstanceState() {
137         final Parcelable superState = super.onSaveInstanceState();
138         if (getDialog() == null || !getDialog().isShowing()) return superState;
139 
140         // Save the dialog state
141         final SavedState myState = new SavedState(superState);
142         myState.progress = mSeekBar.getProgress();
143         myState.oldSpeed = mOldSpeed;
144 
145         // Restore the old state when the activity or dialog is being paused
146         restoreOldState();
147         return myState;
148     }
149 
150     @Override
onRestoreInstanceState(Parcelable state)151     protected void onRestoreInstanceState(Parcelable state) {
152         if (state == null || !state.getClass().equals(SavedState.class)) {
153             // Didn't save state for us in onSaveInstanceState
154             super.onRestoreInstanceState(state);
155             return;
156         }
157 
158         SavedState myState = (SavedState) state;
159         super.onRestoreInstanceState(myState.getSuperState());
160         mOldSpeed = myState.oldSpeed;
161         mIm.tryPointerSpeed(myState.progress + InputManager.MIN_POINTER_SPEED);
162     }
163 
164     private static class SavedState extends BaseSavedState {
165         int progress;
166         int oldSpeed;
167 
SavedState(Parcel source)168         public SavedState(Parcel source) {
169             super(source);
170             progress = source.readInt();
171             oldSpeed = source.readInt();
172         }
173 
174         @Override
writeToParcel(Parcel dest, int flags)175         public void writeToParcel(Parcel dest, int flags) {
176             super.writeToParcel(dest, flags);
177             dest.writeInt(progress);
178             dest.writeInt(oldSpeed);
179         }
180 
SavedState(Parcelable superState)181         public SavedState(Parcelable superState) {
182             super(superState);
183         }
184 
185         public static final Parcelable.Creator<SavedState> CREATOR =
186                 new Parcelable.Creator<SavedState>() {
187 
188             public SavedState createFromParcel(Parcel in) {
189                 return new SavedState(in);
190             }
191 
192             public SavedState[] newArray(int size) {
193                 return new SavedState[size];
194             }
195         };
196     }
197 }
198 
199