11a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov/* 21a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * Copyright (C) 2011 The Android Open Source Project 31a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * 41a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 51a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * you may not use this file except in compliance with the License. 61a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * You may obtain a copy of the License at 71a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * 81a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 91a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * 101a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * Unless required by applicable law or agreed to in writing, software 111a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 121a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * See the License for the specific language governing permissions and 141a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * limitations under the License. 151a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov */ 161a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 171a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovpackage com.android.settings; 181a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 191a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.content.Context; 201a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.content.res.TypedArray; 211a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.os.Parcel; 221a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.os.Parcelable; 231a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.preference.DialogPreference; 241a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.provider.Settings; 251a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.util.AttributeSet; 261a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.view.View; 271a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 281a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.view.accessibility.AccessibilityManager; 291a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 301a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov/** 311a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * Preference for enabling accessibility script injection. It displays a warning 321a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov * dialog before enabling the preference. 331a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov */ 341a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovpublic class AccessibilityEnableScriptInjectionPreference extends DialogPreference { 351a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 361a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private boolean mInjectionAllowed; 371a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private boolean mSendClickAccessibilityEvent; 381a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 391a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public AccessibilityEnableScriptInjectionPreference(Context context, AttributeSet attrs) { 401a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super(context, attrs); 411a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov updateSummary(); 421a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 431a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 441a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public void setInjectionAllowed(boolean injectionAllowed) { 451a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (mInjectionAllowed != injectionAllowed) { 461a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov mInjectionAllowed = injectionAllowed; 471a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov persistBoolean(injectionAllowed); 481a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov updateSummary(); 491a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 501a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 511a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 521a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public boolean isInjectionAllowed() { 531a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return mInjectionAllowed; 541a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 551a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 561a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 571a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected void onBindView(View view) { 581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super.onBindView(view); 591a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov View summaryView = view.findViewById(com.android.internal.R.id.summary); 601a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov sendAccessibilityEvent(summaryView); 611a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 621a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 631a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private void sendAccessibilityEvent(View view) { 641a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov // Since the view is still not attached we create, populate, 651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov // and send the event directly since we do not know when it 661a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov // will be attached and posting commands is not as clean. 671a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getContext()); 681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (mSendClickAccessibilityEvent && accessibilityManager.isEnabled()) { 691a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov AccessibilityEvent event = AccessibilityEvent.obtain(); 701a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov event.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED); 711a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov view.onInitializeAccessibilityEvent(event); 721a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov view.dispatchPopulateAccessibilityEvent(event); 731a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov accessibilityManager.sendAccessibilityEvent(event); 741a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 751a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov mSendClickAccessibilityEvent = false; 761a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 771a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 781a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 791a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected void onClick() { 801a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (isInjectionAllowed()) { 811a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setInjectionAllowed(false); 821a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov // Update the system setting only upon user action. 831a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setSystemSetting(false); 841a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov mSendClickAccessibilityEvent = true; 851a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } else { 861a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super.onClick(); 871a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov mSendClickAccessibilityEvent = false; 881a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 891a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 901a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 911a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 921a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected Object onGetDefaultValue(TypedArray a, int index) { 931a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return a.getBoolean(index, false); 941a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 951a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 961a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 971a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 981a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setInjectionAllowed(restoreValue 991a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov ? getPersistedBoolean(mInjectionAllowed) 1001a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov : (Boolean) defaultValue); 1011a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1021a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1031a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 1041a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected void onDialogClosed(boolean result) { 1051a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setInjectionAllowed(result); 1061a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (result) { 1071a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov // Update the system setting only upon user action. 1081a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setSystemSetting(true); 1091a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1101a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1111a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1121a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 1131a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected Parcelable onSaveInstanceState() { 1141a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov Parcelable superState = super.onSaveInstanceState(); 1151a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (isPersistent()) { 1161a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return superState; 1171a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1181a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov SavedState myState = new SavedState(superState); 1191a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov myState.mInjectionAllowed = mInjectionAllowed; 1201a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return myState; 1211a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1221a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1231a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 1241a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov protected void onRestoreInstanceState(Parcelable state) { 1251a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov if (state == null || !state.getClass().equals(SavedState.class)) { 1261a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super.onRestoreInstanceState(state); 1271a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return; 1281a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1291a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov SavedState myState = (SavedState) state; 1301a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super.onRestoreInstanceState(myState.getSuperState()); 1311a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setInjectionAllowed(myState.mInjectionAllowed); 1321a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1331a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1341a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private void updateSummary() { 1351a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov setSummary(mInjectionAllowed 1361a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov ? getContext().getString(R.string.accessibility_script_injection_allowed) 1371a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov : getContext().getString(R.string.accessibility_script_injection_disallowed)); 1381a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1391a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1401a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private void setSystemSetting(boolean enabled) { 1411a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov Settings.Secure.putInt(getContext().getContentResolver(), 1421a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0); 1431a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1441a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1451a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private static class SavedState extends BaseSavedState { 1461a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov private boolean mInjectionAllowed; 1471a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1481a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public SavedState(Parcel source) { 1491a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super(source); 1501a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov mInjectionAllowed = (source.readInt() == 1); 1511a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1521a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1531a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @Override 1541a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public void writeToParcel(Parcel parcel, int flags) { 1551a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super.writeToParcel(parcel, flags); 1561a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov parcel.writeInt(mInjectionAllowed ? 1 : 0); 1571a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1591a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public SavedState(Parcelable superState) { 1601a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov super(superState); 1611a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1621a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1631a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov @SuppressWarnings("all") 1641a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public static final Parcelable.Creator<SavedState> CREATOR = 1651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov new Parcelable.Creator<SavedState>() { 1661a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public SavedState createFromParcel(Parcel in) { 1671a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return new SavedState(in); 1681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1691a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov 1701a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov public SavedState[] newArray(int size) { 1711a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov return new SavedState[size]; 1721a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1731a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov }; 1741a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov } 1751a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov} 176