1 /* 2 * Copyright (C) 2019 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.car.developeroptions.accessibility; 18 19 import android.app.settings.SettingsEnums; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.content.res.Resources; 23 import android.graphics.Point; 24 import android.media.AudioManager; 25 import android.media.MediaPlayer; 26 import android.media.MediaPlayer.OnPreparedListener; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.view.Display; 30 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 31 import android.view.WindowManager; 32 import android.widget.ImageView; 33 import android.widget.RelativeLayout.LayoutParams; 34 import android.widget.Switch; 35 import android.widget.VideoView; 36 37 import androidx.preference.Preference; 38 import androidx.preference.PreferenceScreen; 39 import androidx.preference.PreferenceViewHolder; 40 41 import com.android.car.developeroptions.R; 42 import com.android.car.developeroptions.widget.SwitchBar; 43 44 public class ToggleScreenMagnificationPreferenceFragment extends 45 ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener { 46 47 protected class VideoPreference extends Preference { 48 private ImageView mVideoBackgroundView; 49 private OnGlobalLayoutListener mLayoutListener; 50 VideoPreference(Context context)51 public VideoPreference(Context context) { 52 super(context); 53 } 54 55 @Override onBindViewHolder(PreferenceViewHolder view)56 public void onBindViewHolder(PreferenceViewHolder view) { 57 super.onBindViewHolder(view); 58 Resources res = getPrefContext().getResources(); 59 final int backgroundAssetWidth = res.getDimensionPixelSize( 60 R.dimen.screen_magnification_video_background_width); 61 final int videoAssetWidth = res 62 .getDimensionPixelSize(R.dimen.screen_magnification_video_width); 63 final int videoAssetHeight = res 64 .getDimensionPixelSize(R.dimen.screen_magnification_video_height); 65 final int videoAssetMarginTop = res.getDimensionPixelSize( 66 R.dimen.screen_magnification_video_margin_top); 67 view.setDividerAllowedAbove(false); 68 view.setDividerAllowedBelow(false); 69 mVideoBackgroundView = (ImageView) view.findViewById(R.id.video_background); 70 final VideoView videoView = (VideoView) view.findViewById(R.id.video); 71 72 // Loop the video. 73 videoView.setOnPreparedListener(new OnPreparedListener() { 74 @Override 75 public void onPrepared(MediaPlayer mediaPlayer) { 76 mediaPlayer.setLooping(true); 77 } 78 }); 79 80 // Make sure the VideoView does not request audio focus. 81 videoView.setAudioFocusRequest(AudioManager.AUDIOFOCUS_NONE); 82 83 // Resolve and set the video content 84 Bundle args = getArguments(); 85 if ((args != null) && args.containsKey( 86 AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID)) { 87 videoView.setVideoURI(Uri.parse(String.format("%s://%s/%s", 88 ContentResolver.SCHEME_ANDROID_RESOURCE, 89 getPrefContext().getPackageName(), 90 args.getInt(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID)))); 91 } 92 93 // Make sure video controls (e.g. for pausing) are not displayed. 94 videoView.setMediaController(null); 95 96 // LayoutListener for adjusting the position of the VideoView on the background image. 97 mLayoutListener = new OnGlobalLayoutListener() { 98 @Override 99 public void onGlobalLayout() { 100 final int backgroundViewWidth = mVideoBackgroundView.getWidth(); 101 102 LayoutParams videoLp = (LayoutParams) videoView.getLayoutParams(); 103 videoLp.width = videoAssetWidth * backgroundViewWidth / backgroundAssetWidth; 104 videoLp.height = videoAssetHeight * backgroundViewWidth / backgroundAssetWidth; 105 videoLp.setMargins(0, 106 videoAssetMarginTop * backgroundViewWidth / backgroundAssetWidth, 0, 0); 107 videoView.setLayoutParams(videoLp); 108 videoView.invalidate(); 109 videoView.start(); 110 } 111 }; 112 113 mVideoBackgroundView.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutListener); 114 } 115 116 @Override onPrepareForRemoval()117 protected void onPrepareForRemoval() { 118 mVideoBackgroundView.getViewTreeObserver() 119 .removeOnGlobalLayoutListener(mLayoutListener); 120 } 121 } 122 123 protected VideoPreference mVideoPreference; 124 protected Preference mConfigWarningPreference; 125 126 private boolean mLaunchFromSuw = false; 127 private boolean mInitialSetting = false; 128 129 @Override onCreate(Bundle savedInstanceState)130 public void onCreate(Bundle savedInstanceState) { 131 super.onCreate(savedInstanceState); 132 133 mVideoPreference = new VideoPreference(getPrefContext()); 134 mVideoPreference.setSelectable(false); 135 mVideoPreference.setPersistent(false); 136 mVideoPreference.setLayoutResource(R.layout.magnification_video_preference); 137 138 mConfigWarningPreference = new Preference(getPrefContext()); 139 mConfigWarningPreference.setSelectable(false); 140 mConfigWarningPreference.setPersistent(false); 141 mConfigWarningPreference.setVisible(false); 142 mConfigWarningPreference.setIcon(R.drawable.ic_warning_24dp); 143 144 final PreferenceScreen preferenceScreen = getPreferenceManager().getPreferenceScreen(); 145 preferenceScreen.setOrderingAsAdded(false); 146 mVideoPreference.setOrder(0); 147 mConfigWarningPreference.setOrder(2); 148 preferenceScreen.addPreference(mVideoPreference); 149 preferenceScreen.addPreference(mConfigWarningPreference); 150 } 151 152 @Override onResume()153 public void onResume() { 154 super.onResume(); 155 156 VideoView videoView = (VideoView) getView().findViewById(R.id.video); 157 if (videoView != null) { 158 videoView.start(); 159 } 160 161 updateConfigurationWarningIfNeeded(); 162 } 163 164 @Override getMetricsCategory()165 public int getMetricsCategory() { 166 // TODO: Distinguish between magnification modes 167 return SettingsEnums.ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION; 168 } 169 170 @Override onSwitchChanged(Switch switchView, boolean isChecked)171 public void onSwitchChanged(Switch switchView, boolean isChecked) { 172 onPreferenceToggled(mPreferenceKey, isChecked); 173 } 174 175 @Override onPreferenceToggled(String preferenceKey, boolean enabled)176 protected void onPreferenceToggled(String preferenceKey, boolean enabled) { 177 MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled); 178 updateConfigurationWarningIfNeeded(); 179 } 180 181 @Override onInstallSwitchBarToggleSwitch()182 protected void onInstallSwitchBarToggleSwitch() { 183 super.onInstallSwitchBarToggleSwitch(); 184 185 mSwitchBar.setCheckedInternal( 186 MagnificationPreferenceFragment.isChecked(getContentResolver(), mPreferenceKey)); 187 mSwitchBar.addOnSwitchChangeListener(this); 188 } 189 190 @Override onRemoveSwitchBarToggleSwitch()191 protected void onRemoveSwitchBarToggleSwitch() { 192 super.onRemoveSwitchBarToggleSwitch(); 193 mSwitchBar.removeOnSwitchChangeListener(this); 194 } 195 196 @Override onProcessArguments(Bundle arguments)197 protected void onProcessArguments(Bundle arguments) { 198 super.onProcessArguments(arguments); 199 if (arguments == null) { 200 return; 201 } 202 203 if (arguments.containsKey(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID)) { 204 mVideoPreference.setVisible(true); 205 final int resId = arguments.getInt( 206 AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID); 207 } else { 208 mVideoPreference.setVisible(false); 209 } 210 211 if (arguments.containsKey(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW)) { 212 mLaunchFromSuw = arguments.getBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW); 213 } 214 215 if (arguments.containsKey(AccessibilitySettings.EXTRA_CHECKED)) { 216 mInitialSetting = arguments.getBoolean(AccessibilitySettings.EXTRA_CHECKED); 217 } 218 219 if (arguments.containsKey(AccessibilitySettings.EXTRA_TITLE_RES)) { 220 final int titleRes = arguments.getInt(AccessibilitySettings.EXTRA_TITLE_RES); 221 if (titleRes > 0) { 222 getActivity().setTitle(titleRes); 223 } 224 } 225 } 226 updateConfigurationWarningIfNeeded()227 private void updateConfigurationWarningIfNeeded() { 228 final CharSequence warningMessage = 229 MagnificationPreferenceFragment.getConfigurationWarningStringForSecureSettingsKey( 230 mPreferenceKey, getPrefContext()); 231 if (warningMessage != null) { 232 mConfigWarningPreference.setSummary(warningMessage); 233 } 234 mConfigWarningPreference.setVisible(warningMessage != null); 235 } 236 getScreenWidth(Context context)237 private static int getScreenWidth(Context context) { 238 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 239 Display display = wm.getDefaultDisplay(); 240 Point size = new Point(); 241 display.getSize(size); 242 return size.x; 243 } 244 } 245