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 17package com.android.settings; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.preference.DialogPreference; 24import android.provider.Settings; 25import android.util.AttributeSet; 26import android.view.View; 27import android.view.accessibility.AccessibilityEvent; 28import android.view.accessibility.AccessibilityManager; 29 30/** 31 * Preference for enabling accessibility script injection. It displays a warning 32 * dialog before enabling the preference. 33 */ 34public class AccessibilityEnableScriptInjectionPreference extends DialogPreference { 35 36 private boolean mInjectionAllowed; 37 private boolean mSendClickAccessibilityEvent; 38 39 public AccessibilityEnableScriptInjectionPreference(Context context, AttributeSet attrs) { 40 super(context, attrs); 41 updateSummary(); 42 } 43 44 public void setInjectionAllowed(boolean injectionAllowed) { 45 if (mInjectionAllowed != injectionAllowed) { 46 mInjectionAllowed = injectionAllowed; 47 persistBoolean(injectionAllowed); 48 updateSummary(); 49 } 50 } 51 52 public boolean isInjectionAllowed() { 53 return mInjectionAllowed; 54 } 55 56 @Override 57 protected void onBindView(View view) { 58 super.onBindView(view); 59 View summaryView = view.findViewById(com.android.internal.R.id.summary); 60 sendAccessibilityEvent(summaryView); 61 } 62 63 private void sendAccessibilityEvent(View view) { 64 // Since the view is still not attached we create, populate, 65 // and send the event directly since we do not know when it 66 // will be attached and posting commands is not as clean. 67 AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getContext()); 68 if (mSendClickAccessibilityEvent && accessibilityManager.isEnabled()) { 69 AccessibilityEvent event = AccessibilityEvent.obtain(); 70 event.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED); 71 view.onInitializeAccessibilityEvent(event); 72 view.dispatchPopulateAccessibilityEvent(event); 73 accessibilityManager.sendAccessibilityEvent(event); 74 } 75 mSendClickAccessibilityEvent = false; 76 } 77 78 @Override 79 protected void onClick() { 80 if (isInjectionAllowed()) { 81 setInjectionAllowed(false); 82 // Update the system setting only upon user action. 83 setSystemSetting(false); 84 mSendClickAccessibilityEvent = true; 85 } else { 86 super.onClick(); 87 mSendClickAccessibilityEvent = false; 88 } 89 } 90 91 @Override 92 protected Object onGetDefaultValue(TypedArray a, int index) { 93 return a.getBoolean(index, false); 94 } 95 96 @Override 97 protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 98 setInjectionAllowed(restoreValue 99 ? getPersistedBoolean(mInjectionAllowed) 100 : (Boolean) defaultValue); 101 } 102 103 @Override 104 protected void onDialogClosed(boolean result) { 105 setInjectionAllowed(result); 106 if (result) { 107 // Update the system setting only upon user action. 108 setSystemSetting(true); 109 } 110 } 111 112 @Override 113 protected Parcelable onSaveInstanceState() { 114 Parcelable superState = super.onSaveInstanceState(); 115 if (isPersistent()) { 116 return superState; 117 } 118 SavedState myState = new SavedState(superState); 119 myState.mInjectionAllowed = mInjectionAllowed; 120 return myState; 121 } 122 123 @Override 124 protected void onRestoreInstanceState(Parcelable state) { 125 if (state == null || !state.getClass().equals(SavedState.class)) { 126 super.onRestoreInstanceState(state); 127 return; 128 } 129 SavedState myState = (SavedState) state; 130 super.onRestoreInstanceState(myState.getSuperState()); 131 setInjectionAllowed(myState.mInjectionAllowed); 132 } 133 134 private void updateSummary() { 135 setSummary(mInjectionAllowed 136 ? getContext().getString(R.string.accessibility_script_injection_allowed) 137 : getContext().getString(R.string.accessibility_script_injection_disallowed)); 138 } 139 140 private void setSystemSetting(boolean enabled) { 141 Settings.Secure.putInt(getContext().getContentResolver(), 142 Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0); 143 } 144 145 private static class SavedState extends BaseSavedState { 146 private boolean mInjectionAllowed; 147 148 public SavedState(Parcel source) { 149 super(source); 150 mInjectionAllowed = (source.readInt() == 1); 151 } 152 153 @Override 154 public void writeToParcel(Parcel parcel, int flags) { 155 super.writeToParcel(parcel, flags); 156 parcel.writeInt(mInjectionAllowed ? 1 : 0); 157 } 158 159 public SavedState(Parcelable superState) { 160 super(superState); 161 } 162 163 @SuppressWarnings("all") 164 public static final Parcelable.Creator<SavedState> CREATOR = 165 new Parcelable.Creator<SavedState>() { 166 public SavedState createFromParcel(Parcel in) { 167 return new SavedState(in); 168 } 169 170 public SavedState[] newArray(int size) { 171 return new SavedState[size]; 172 } 173 }; 174 } 175} 176