diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8b9f3680867..3f9978c3af8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2925,6 +2925,24 @@ android:value="com.android.settings.deletionhelper.DeletionHelperFragment" /> + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/gesture_preference.xml b/res/layout/gesture_preference.xml new file mode 100644 index 00000000000..9a388c592b9 --- /dev/null +++ b/res/layout/gesture_preference.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/raw/gesture_ambient_move_lift.mp4 b/res/raw/gesture_ambient_move_lift.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/raw/gesture_ambient_tap.mp4 b/res/raw/gesture_ambient_tap.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/raw/gesture_double_tap.mp4 b/res/raw/gesture_double_tap.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/raw/gesture_fingerprint_swipe.mp4 b/res/raw/gesture_fingerprint_swipe.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/raw/gesture_twist.mp4 b/res/raw/gesture_twist.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/values/attrs.xml b/res/values/attrs.xml index ca3d247354d..ffc233b3e60 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -137,4 +137,10 @@ + + + + + + diff --git a/res/values/colors.xml b/res/values/colors.xml index a462edc3e98..b2d043f6a88 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -131,4 +131,7 @@ @color/accent_material_light #ff7fcac3 + + #f5f5f5 + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index c50e2267784..c4e471ff44f 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -296,4 +296,11 @@ 16dp + + 56dp + 206dp + 206dp + 206dp + 206dp + 20dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 4a5650f935e..971ec82f94e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7660,4 +7660,35 @@ Automatic Storage Management Service + + Gestures + + + Jump to Camera + + + To quickly open camera, just double-tap the power button. Works from any screen. + + + Flip camera + + + To switch between front and back cameras, double-twist. + + + Quick screen check + + + To check your phone without waking it up fully, nudge or pick it up. + + + Swipe for notifications + + + To check your notifications from any screen, swipe down on the fingerprint sensor. + + + On + Off + diff --git a/res/xml/gesture_settings.xml b/res/xml/gesture_settings.xml new file mode 100644 index 00000000000..e68d8f55a5f --- /dev/null +++ b/res/xml/gesture_settings.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 1bf1e0e41b2..f4a407af322 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -84,6 +84,7 @@ public class Settings extends SettingsActivity { public static class AccountSyncSettingsActivity extends SettingsActivity { /* empty */ } public static class AccountSettingsActivity extends SettingsActivity { /* empty */ } public static class AccountSyncSettingsInAddAccountActivity extends SettingsActivity { /* empty */ } + public static class GestureSettingsActivity extends SettingsActivity { /* empty */ } public static class CryptKeeperSettingsActivity extends SettingsActivity { /* empty */ } public static class DeviceAdminSettingsActivity extends SettingsActivity { /* empty */ } public static class DataUsageSummaryActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 330c9ea2170..223d5367c98 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -85,6 +85,7 @@ import com.android.settings.deviceinfo.StorageSettings; import com.android.settings.fuelgauge.BatterySaverSettings; import com.android.settings.fuelgauge.PowerUsageDetail; import com.android.settings.fuelgauge.PowerUsageSummary; +import com.android.settings.gestures.GestureSettings; import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment; import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.inputmethod.KeyboardLayoutPickerFragment; @@ -242,6 +243,7 @@ public class SettingsActivity extends SettingsDrawerActivity Settings.StorageSettingsActivity.class.getName(), Settings.ManageApplicationsActivity.class.getName(), Settings.PowerUsageSummaryActivity.class.getName(), + Settings.GestureSettingsActivity.class.getName(), //personal_section Settings.LocationSettingsActivity.class.getName(), Settings.SecuritySettingsActivity.class.getName(), @@ -301,6 +303,7 @@ public class SettingsActivity extends SettingsDrawerActivity PowerUsageSummary.class.getName(), AccountSyncSettings.class.getName(), AccountSettings.class.getName(), + GestureSettings.class.getName(), CryptKeeperSettings.class.getName(), DataUsageSummary.class.getName(), DreamSettings.class.getName(), diff --git a/src/com/android/settings/gestures/GesturePreference.java b/src/com/android/settings/gestures/GesturePreference.java new file mode 100644 index 00000000000..1541aece094 --- /dev/null +++ b/src/com/android/settings/gestures/GesturePreference.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.settings.gestures; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.SurfaceTexture; +import android.media.MediaMetadataRetriever; +import android.media.MediaPlayer; +import android.net.Uri; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.PreferenceViewHolder; +import android.view.MotionEvent; +import android.view.View; +import android.view.Surface; +import android.view.TextureView; +import android.widget.ImageView; +import android.util.AttributeSet; +import android.util.Log; + +import com.android.settings.R; + +/** + * Preference item for a gesture with a switch to signify if it should be enabled. + * This shows the title and description of the gesture along with an animation showing how to do + * the gesture + */ +public class GesturePreference extends SwitchPreference { + private static final String TAG = "GesturePreference"; + private Uri mVideoPath; + private Context mContext; + private MediaPlayer mMediaPlayer; + private MediaMetadataRetriever mMediaMetadata; + + public GesturePreference(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + setLayoutResource(R.layout.gesture_preference); + TypedArray attributes = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.GesturePreference, + 0, 0); + try { + int animation = attributes.getResourceId(R.styleable.GesturePreference_animation, 0); + mVideoPath = Uri.parse( + "android.resource://" + context.getPackageName() + "/" + animation); + mMediaMetadata = new MediaMetadataRetriever(); + mMediaMetadata.setDataSource(mContext, mVideoPath); + } catch (Exception e) { + // resource not available, show blank view + } finally { + attributes.recycle(); + } + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + final TextureView video = (TextureView) holder.findViewById(R.id.gesture_video); + final ImageView imageView = (ImageView) holder.findViewById(R.id.gesture_image); + + video.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mMediaPlayer != null) { + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.pause(); + } else { + mMediaPlayer.start(); + imageView.setVisibility(View.GONE); + } + } + return true; + } + return false; + } + }); + + video.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { + mMediaPlayer = MediaPlayer.create(mContext, mVideoPath); + if (mMediaPlayer != null) { + mMediaPlayer.setSurface(new Surface(surfaceTexture)); + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + mediaPlayer.setLooping(true); + } + }); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + imageView.setVisibility(View.VISIBLE); + if (mMediaPlayer != null) { + mMediaPlayer.stop(); + mMediaPlayer.reset(); + mMediaPlayer.release(); + } + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + } + }); + + if (mMediaPlayer == null) { + Bitmap bitmap = mMediaMetadata.getFrameAtTime(0); + if (bitmap != null) { + imageView.setImageDrawable(new BitmapDrawable(bitmap)); + } + imageView.setVisibility(View.VISIBLE); + } + + } + +} diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java new file mode 100644 index 00000000000..56f4184efa3 --- /dev/null +++ b/src/com/android/settings/gestures/GestureSettings.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.gestures; + +import android.os.Bundle; +import android.support.v7.preference.PreferenceScreen; +import android.provider.Settings; +import android.support.v7.preference.Preference; +import android.util.Log; + +import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +/** + * Top level fragment for gesture settings. + * This will create individual switch preference for each gesture and handle updates when each + * preference is updated + */ +public class GestureSettings extends SettingsPreferenceFragment implements + Preference.OnPreferenceChangeListener { + + private static final String TAG = "GestureSettings"; + private static final String PREF_KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power"; + private static final String PREF_KEY_DOUBLE_TWIST = "gesture_double_twist"; + private static final String PREF_KEY_PICK_UP_AND_NUDGE = "gesture_pick_up_and_nudge"; + private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.gesture_settings); + + // Double tap power for camera + int cameraDisabled = Settings.Secure.getInt(getActivity().getContentResolver(), + Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 1); + GesturePreference preference = + (GesturePreference) findPreference(PREF_KEY_DOUBLE_TAP_POWER); + preference.setChecked(cameraDisabled == 0); + preference.setOnPreferenceChangeListener(this); + + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enabled = (boolean) newValue; + if (PREF_KEY_DOUBLE_TAP_POWER.equals(preference.getKey())) { + Settings.Secure.putInt(getActivity().getContentResolver(), + Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, enabled ? 0 : 1); + } + return true; + } + + @Override + protected int getMetricsCategory() { + return MetricsEvent.SETTINGS_GESTURES; + } + +} \ No newline at end of file