Merge changes from topic "edit_menu_v2" into rvc-dev am: 6f22413c6f

Change-Id: I993dd5584b929f97d067b0824744dbe90ca38cad
This commit is contained in:
Automerger Merge Worker
2020-03-09 08:21:29 +00:00
9 changed files with 573 additions and 178 deletions

View File

@@ -28,8 +28,6 @@ public final class ShortcutConstants {
private ShortcutConstants() {} private ShortcutConstants() {}
public static final char SERVICES_SEPARATOR = ':'; public static final char SERVICES_SEPARATOR = ':';
public static final float DISABLED_ALPHA = 0.5f;
public static final float ENABLED_ALPHA = 1.0f;
/** /**
* Annotation for different user shortcut type UI type. * Annotation for different user shortcut type UI type.
@@ -79,6 +77,21 @@ public final class ShortcutConstants {
int BOUNCE = 3; int BOUNCE = 3;
} }
/**
* Annotation for different shortcut target.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
TargetType.ACCESSIBILITY_SERVICE,
TargetType.ACCESSIBILITY_ACTIVITY,
TargetType.WHITE_LISTING,
})
public @interface TargetType {
int ACCESSIBILITY_SERVICE = 0;
int ACCESSIBILITY_ACTIVITY = 1;
int WHITE_LISTING = 2;
}
/** /**
* Annotation for different shortcut menu mode. * Annotation for different shortcut menu mode.
* *

View File

@@ -38,6 +38,33 @@ public final class ShortcutUtils {
private static final TextUtils.SimpleStringSplitter sStringColonSplitter = private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR); new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR);
/**
* Opts in component name into colon-separated {@link UserShortcutType}
* key's string in Settings.
*
* @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
* @param componentId The component id that need to be opted out from Settings.
*/
public static void optInValueToSettings(Context context, @UserShortcutType int shortcutType,
String componentId) {
final StringJoiner joiner = new StringJoiner(String.valueOf(SERVICES_SEPARATOR));
final String targetKey = convertToKey(shortcutType);
final String targetString = Settings.Secure.getString(context.getContentResolver(),
targetKey);
if (hasValueInSettings(context, shortcutType, componentId)) {
return;
}
if (!TextUtils.isEmpty(targetString)) {
joiner.add(targetString);
}
joiner.add(componentId);
Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
}
/** /**
* Opts out component name into colon-separated {@code shortcutType} key's string in Settings. * Opts out component name into colon-separated {@code shortcutType} key's string in Settings.
* *

View File

@@ -23,10 +23,10 @@ import static com.android.internal.accessibility.AccessibilityShortcutController
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityServiceFragmentType; import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityServiceFragmentType;
import static com.android.internal.accessibility.common.ShortcutConstants.DISABLED_ALPHA;
import static com.android.internal.accessibility.common.ShortcutConstants.ENABLED_ALPHA;
import static com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode; import static com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
import static com.android.internal.accessibility.common.ShortcutConstants.TargetType;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType; import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.COMPONENT_ID; import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.COMPONENT_ID;
import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.FRAGMENT_TYPE; import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.FRAGMENT_TYPE;
import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.ICON_ID; import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.ICON_ID;
@@ -36,6 +36,7 @@ import static com.android.internal.accessibility.util.AccessibilityUtils.getAcce
import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState; import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState;
import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType; import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType;
import static com.android.internal.accessibility.util.ShortcutUtils.hasValuesInSettings; import static com.android.internal.accessibility.util.ShortcutUtils.hasValuesInSettings;
import static com.android.internal.accessibility.util.ShortcutUtils.optInValueToSettings;
import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings; import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
import static com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkArgument;
@@ -50,11 +51,12 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.storage.StorageManager;
import android.provider.Settings; import android.provider.Settings;
import android.text.BidiFormatter;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -62,28 +64,33 @@ import android.view.Window;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.FrameLayout; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Switch; import android.widget.Switch;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.R; import com.android.internal.R;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
/** /**
* Activity used to display and persist a service or feature target for the Accessibility button. * Activity used to display and persist a service or feature target for the Accessibility button.
*/ */
public class AccessibilityButtonChooserActivity extends Activity { public class AccessibilityButtonChooserActivity extends Activity {
@ShortcutType @ShortcutType
private int mShortcutType; private static int sShortcutType;
@UserShortcutType @UserShortcutType
private int mShortcutUserType; private int mShortcutUserType;
private final List<AccessibilityButtonTarget> mTargets = new ArrayList<>(); private final List<AccessibilityButtonTarget> mTargets = new ArrayList<>();
private AlertDialog mAlertDialog; private AlertDialog mAlertDialog;
private AlertDialog mEnableDialog;
private TargetAdapter mTargetAdapter; private TargetAdapter mTargetAdapter;
private AccessibilityButtonTarget mCurrentCheckedTarget;
private static final String[][] WHITE_LISTING_FEATURES = { private static final String[][] WHITE_LISTING_FEATURES = {
{ {
@@ -118,19 +125,19 @@ public class AccessibilityButtonChooserActivity extends Activity {
requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_NO_TITLE);
} }
mShortcutType = getIntent().getIntExtra(AccessibilityManager.EXTRA_SHORTCUT_TYPE, sShortcutType = getIntent().getIntExtra(AccessibilityManager.EXTRA_SHORTCUT_TYPE,
/* unexpectedShortcutType */ -1); /* unexpectedShortcutType */ -1);
final boolean existInShortcutType = (mShortcutType == ACCESSIBILITY_BUTTON) final boolean existInShortcutType = (sShortcutType == ACCESSIBILITY_BUTTON)
|| (mShortcutType == ACCESSIBILITY_SHORTCUT_KEY); || (sShortcutType == ACCESSIBILITY_SHORTCUT_KEY);
checkArgument(existInShortcutType, "Unexpected shortcut type: " + mShortcutType); checkArgument(existInShortcutType, "Unexpected shortcut type: " + sShortcutType);
mShortcutUserType = convertToUserType(mShortcutType); mShortcutUserType = convertToUserType(sShortcutType);
mTargets.addAll(getServiceTargets(this, mShortcutType)); mTargets.addAll(getServiceTargets(this, sShortcutType));
final String selectDialogTitle = final String selectDialogTitle =
getString(R.string.accessibility_select_shortcut_menu_title); getString(R.string.accessibility_select_shortcut_menu_title);
mTargetAdapter = new TargetAdapter(mTargets, mShortcutType); mTargetAdapter = new TargetAdapter(mTargets);
mAlertDialog = new AlertDialog.Builder(this) mAlertDialog = new AlertDialog.Builder(this)
.setTitle(selectDialogTitle) .setTitle(selectDialogTitle)
.setAdapter(mTargetAdapter, /* listener= */ null) .setAdapter(mTargetAdapter, /* listener= */ null)
@@ -151,15 +158,21 @@ public class AccessibilityButtonChooserActivity extends Activity {
private static List<AccessibilityButtonTarget> getServiceTargets(@NonNull Context context, private static List<AccessibilityButtonTarget> getServiceTargets(@NonNull Context context,
@ShortcutType int shortcutType) { @ShortcutType int shortcutType) {
final List<AccessibilityButtonTarget> targets = getInstalledServiceTargets(context);
final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
final List<String> requiredTargets = ams.getAccessibilityShortcutTargets(shortcutType);
targets.removeIf(target -> !requiredTargets.contains(target.getId()));
return targets;
}
private static List<AccessibilityButtonTarget> getInstalledServiceTargets(
@NonNull Context context) {
final List<AccessibilityButtonTarget> targets = new ArrayList<>(); final List<AccessibilityButtonTarget> targets = new ArrayList<>();
targets.addAll(getAccessibilityServiceTargets(context)); targets.addAll(getAccessibilityServiceTargets(context));
targets.addAll(getAccessibilityActivityTargets(context)); targets.addAll(getAccessibilityActivityTargets(context));
targets.addAll(getWhiteListingServiceTargets(context)); targets.addAll(getWhiteListingServiceTargets(context));
final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
final List<String> requiredTargets = ams.getAccessibilityShortcutTargets(shortcutType);
targets.removeIf(target -> !requiredTargets.contains(target.getId()));
return targets; return targets;
} }
@@ -174,6 +187,14 @@ public class AccessibilityButtonChooserActivity extends Activity {
final List<AccessibilityButtonTarget> targets = new ArrayList<>(installedServices.size()); final List<AccessibilityButtonTarget> targets = new ArrayList<>(installedServices.size());
for (AccessibilityServiceInfo info : installedServices) { for (AccessibilityServiceInfo info : installedServices) {
final int targetSdk =
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion;
final boolean hasRequestAccessibilityButtonFlag =
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
if ((targetSdk < Build.VERSION_CODES.R) && !hasRequestAccessibilityButtonFlag
&& (sShortcutType == ACCESSIBILITY_BUTTON)) {
continue;
}
targets.add(new AccessibilityButtonTarget(context, info)); targets.add(new AccessibilityButtonTarget(context, info));
} }
@@ -249,35 +270,31 @@ public class AccessibilityButtonChooserActivity extends Activity {
} }
} }
private void disableService(String componentId) { private void setServiceEnabled(String componentId, boolean enabled) {
if (isWhiteListingService(componentId)) { if (isWhiteListingService(componentId)) {
setWhiteListingServiceEnabled(componentId, /* settingsValueOff */ 0); setWhiteListingServiceEnabled(componentId,
enabled ? /* settingsValueOn */ 1 : /* settingsValueOff */ 0);
} else { } else {
final ComponentName componentName = ComponentName.unflattenFromString(componentId); final ComponentName componentName = ComponentName.unflattenFromString(componentId);
setAccessibilityServiceState(this, componentName, /* enabled= */ false); setAccessibilityServiceState(this, componentName, enabled);
} }
} }
private static class ViewHolder { private static class ViewHolder {
View mItemView; View mItemView;
CheckBox mCheckBox;
ImageView mIconView; ImageView mIconView;
TextView mLabelView; TextView mLabelView;
FrameLayout mItemContainer;
ImageView mActionViewItem;
Switch mSwitchItem; Switch mSwitchItem;
} }
private static class TargetAdapter extends BaseAdapter { private static class TargetAdapter extends BaseAdapter {
@ShortcutMenuMode @ShortcutMenuMode
private int mShortcutMenuMode = ShortcutMenuMode.LAUNCH; private int mShortcutMenuMode = ShortcutMenuMode.LAUNCH;
@ShortcutType
private int mShortcutButtonType;
private List<AccessibilityButtonTarget> mButtonTargets; private List<AccessibilityButtonTarget> mButtonTargets;
TargetAdapter(List<AccessibilityButtonTarget> targets, TargetAdapter(List<AccessibilityButtonTarget> targets) {
@ShortcutType int shortcutButtonType) {
this.mButtonTargets = targets; this.mButtonTargets = targets;
this.mShortcutButtonType = shortcutButtonType;
} }
void setShortcutMenuMode(@ShortcutMenuMode int shortcutMenuMode) { void setShortcutMenuMode(@ShortcutMenuMode int shortcutMenuMode) {
@@ -314,13 +331,11 @@ public class AccessibilityButtonChooserActivity extends Activity {
false); false);
holder = new ViewHolder(); holder = new ViewHolder();
holder.mItemView = convertView; holder.mItemView = convertView;
holder.mCheckBox = convertView.findViewById(
R.id.accessibility_button_target_checkbox);
holder.mIconView = convertView.findViewById(R.id.accessibility_button_target_icon); holder.mIconView = convertView.findViewById(R.id.accessibility_button_target_icon);
holder.mLabelView = convertView.findViewById( holder.mLabelView = convertView.findViewById(
R.id.accessibility_button_target_label); R.id.accessibility_button_target_label);
holder.mItemContainer = convertView.findViewById(
R.id.accessibility_button_target_item_container);
holder.mActionViewItem = convertView.findViewById(
R.id.accessibility_button_target_view_item);
holder.mSwitchItem = convertView.findViewById( holder.mSwitchItem = convertView.findViewById(
R.id.accessibility_button_target_switch_item); R.id.accessibility_button_target_switch_item);
convertView.setTag(holder); convertView.setTag(holder);
@@ -329,9 +344,6 @@ public class AccessibilityButtonChooserActivity extends Activity {
} }
final AccessibilityButtonTarget target = mButtonTargets.get(position); final AccessibilityButtonTarget target = mButtonTargets.get(position);
holder.mIconView.setImageDrawable(target.getDrawable());
holder.mLabelView.setText(target.getLabel());
updateActionItem(context, holder, target); updateActionItem(context, holder, target);
return convertView; return convertView;
@@ -342,58 +354,42 @@ public class AccessibilityButtonChooserActivity extends Activity {
switch (target.getFragmentType()) { switch (target.getFragmentType()) {
case AccessibilityServiceFragmentType.LEGACY: case AccessibilityServiceFragmentType.LEGACY:
updateLegacyActionItemVisibility(context, holder); updateLegacyActionItemVisibility(holder, target);
break; break;
case AccessibilityServiceFragmentType.INVISIBLE: case AccessibilityServiceFragmentType.INVISIBLE:
updateInvisibleActionItemVisibility(context, holder); updateInvisibleActionItemVisibility(holder, target);
break; break;
case AccessibilityServiceFragmentType.INTUITIVE: case AccessibilityServiceFragmentType.INTUITIVE:
updateIntuitiveActionItemVisibility(context, holder, target); updateIntuitiveActionItemVisibility(context, holder, target);
break; break;
case AccessibilityServiceFragmentType.BOUNCE: case AccessibilityServiceFragmentType.BOUNCE:
updateBounceActionItemVisibility(context, holder); updateBounceActionItemVisibility(holder, target);
break; break;
default: default:
throw new IllegalStateException("Unexpected fragment type"); throw new IllegalStateException("Unexpected fragment type");
} }
} }
private void updateLegacyActionItemVisibility(@NonNull Context context, private void updateLegacyActionItemVisibility(@NonNull ViewHolder holder,
@NonNull ViewHolder holder) { AccessibilityButtonTarget target) {
final boolean isLaunchMenuMode = (mShortcutMenuMode == ShortcutMenuMode.LAUNCH); final boolean isLaunchMenuMode = (mShortcutMenuMode == ShortcutMenuMode.LAUNCH);
final boolean isHardwareButtonTriggered =
(mShortcutButtonType == ACCESSIBILITY_SHORTCUT_KEY);
final boolean enabledState = (isLaunchMenuMode || isHardwareButtonTriggered);
final ColorMatrix grayScaleMatrix = new ColorMatrix();
grayScaleMatrix.setSaturation(/* grayScale */0);
holder.mIconView.setColorFilter(enabledState holder.mCheckBox.setChecked(!isLaunchMenuMode && target.isChecked());
? null : new ColorMatrixColorFilter(grayScaleMatrix)); holder.mCheckBox.setVisibility(isLaunchMenuMode ? View.GONE : View.VISIBLE);
holder.mIconView.setAlpha(enabledState holder.mIconView.setImageDrawable(target.getDrawable());
? ENABLED_ALPHA : DISABLED_ALPHA); holder.mLabelView.setText(target.getLabel());
holder.mLabelView.setEnabled(enabledState);
holder.mActionViewItem.setEnabled(enabledState);
holder.mActionViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item));
holder.mActionViewItem.setVisibility(View.VISIBLE);
holder.mSwitchItem.setVisibility(View.GONE); holder.mSwitchItem.setVisibility(View.GONE);
holder.mItemContainer.setVisibility(isLaunchMenuMode ? View.GONE : View.VISIBLE);
holder.mItemView.setEnabled(enabledState);
holder.mItemView.setClickable(!enabledState);
} }
private void updateInvisibleActionItemVisibility(@NonNull Context context, private void updateInvisibleActionItemVisibility(@NonNull ViewHolder holder,
@NonNull ViewHolder holder) { AccessibilityButtonTarget target) {
holder.mIconView.setColorFilter(null); final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
holder.mIconView.setAlpha(ENABLED_ALPHA);
holder.mLabelView.setEnabled(true); holder.mCheckBox.setChecked(isEditMenuMode && target.isChecked());
holder.mActionViewItem.setEnabled(true); holder.mCheckBox.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
holder.mActionViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item)); holder.mIconView.setImageDrawable(target.getDrawable());
holder.mActionViewItem.setVisibility(View.VISIBLE); holder.mLabelView.setText(target.getLabel());
holder.mSwitchItem.setVisibility(View.GONE); holder.mSwitchItem.setVisibility(View.GONE);
holder.mItemContainer.setVisibility((mShortcutMenuMode == ShortcutMenuMode.EDIT)
? View.VISIBLE : View.GONE);
holder.mItemView.setEnabled(true);
holder.mItemView.setClickable(false);
} }
private void updateIntuitiveActionItemVisibility(@NonNull Context context, private void updateIntuitiveActionItemVisibility(@NonNull Context context,
@@ -403,37 +399,31 @@ public class AccessibilityButtonChooserActivity extends Activity {
? isWhiteListingServiceEnabled(context, target) ? isWhiteListingServiceEnabled(context, target)
: isAccessibilityServiceEnabled(context, target); : isAccessibilityServiceEnabled(context, target);
holder.mIconView.setColorFilter(null); holder.mCheckBox.setChecked(isEditMenuMode && target.isChecked());
holder.mIconView.setAlpha(ENABLED_ALPHA); holder.mCheckBox.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
holder.mLabelView.setEnabled(true); holder.mIconView.setImageDrawable(target.getDrawable());
holder.mActionViewItem.setEnabled(true); holder.mLabelView.setText(target.getLabel());
holder.mActionViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item));
holder.mActionViewItem.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
holder.mSwitchItem.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE); holder.mSwitchItem.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
holder.mSwitchItem.setChecked(!isEditMenuMode && isServiceEnabled); holder.mSwitchItem.setChecked(!isEditMenuMode && isServiceEnabled);
holder.mItemContainer.setVisibility(View.VISIBLE);
holder.mItemView.setEnabled(true);
holder.mItemView.setClickable(false);
} }
private void updateBounceActionItemVisibility(@NonNull Context context, private void updateBounceActionItemVisibility(@NonNull ViewHolder holder,
@NonNull ViewHolder holder) { AccessibilityButtonTarget target) {
holder.mIconView.setColorFilter(null); final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
holder.mIconView.setAlpha(ENABLED_ALPHA);
holder.mLabelView.setEnabled(true); holder.mCheckBox.setChecked(isEditMenuMode && target.isChecked());
holder.mActionViewItem.setEnabled(true); holder.mCheckBox.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
holder.mActionViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item)); holder.mIconView.setImageDrawable(target.getDrawable());
holder.mActionViewItem.setVisibility((mShortcutMenuMode == ShortcutMenuMode.EDIT) holder.mLabelView.setText(target.getLabel());
? View.VISIBLE : View.GONE);
holder.mSwitchItem.setVisibility(View.GONE); holder.mSwitchItem.setVisibility(View.GONE);
holder.mItemContainer.setVisibility(View.VISIBLE);
holder.mItemView.setEnabled(true);
holder.mItemView.setClickable(false);
} }
} }
private static class AccessibilityButtonTarget { private static class AccessibilityButtonTarget {
private String mId; private String mId;
@TargetType
private int mType;
private boolean mChecked;
private CharSequence mLabel; private CharSequence mLabel;
private Drawable mDrawable; private Drawable mDrawable;
@AccessibilityServiceFragmentType @AccessibilityServiceFragmentType
@@ -442,6 +432,8 @@ public class AccessibilityButtonChooserActivity extends Activity {
AccessibilityButtonTarget(@NonNull Context context, AccessibilityButtonTarget(@NonNull Context context,
@NonNull AccessibilityServiceInfo serviceInfo) { @NonNull AccessibilityServiceInfo serviceInfo) {
this.mId = serviceInfo.getComponentName().flattenToString(); this.mId = serviceInfo.getComponentName().flattenToString();
this.mType = TargetType.ACCESSIBILITY_SERVICE;
this.mChecked = isTargetShortcutUsed(context, mId);
this.mLabel = serviceInfo.getResolveInfo().loadLabel(context.getPackageManager()); this.mLabel = serviceInfo.getResolveInfo().loadLabel(context.getPackageManager());
this.mDrawable = serviceInfo.getResolveInfo().loadIcon(context.getPackageManager()); this.mDrawable = serviceInfo.getResolveInfo().loadIcon(context.getPackageManager());
this.mFragmentType = getAccessibilityServiceFragmentType(serviceInfo); this.mFragmentType = getAccessibilityServiceFragmentType(serviceInfo);
@@ -450,6 +442,8 @@ public class AccessibilityButtonChooserActivity extends Activity {
AccessibilityButtonTarget(@NonNull Context context, AccessibilityButtonTarget(@NonNull Context context,
@NonNull AccessibilityShortcutInfo shortcutInfo) { @NonNull AccessibilityShortcutInfo shortcutInfo) {
this.mId = shortcutInfo.getComponentName().flattenToString(); this.mId = shortcutInfo.getComponentName().flattenToString();
this.mType = TargetType.ACCESSIBILITY_ACTIVITY;
this.mChecked = isTargetShortcutUsed(context, mId);
this.mLabel = shortcutInfo.getActivityInfo().loadLabel(context.getPackageManager()); this.mLabel = shortcutInfo.getActivityInfo().loadLabel(context.getPackageManager());
this.mDrawable = shortcutInfo.getActivityInfo().loadIcon(context.getPackageManager()); this.mDrawable = shortcutInfo.getActivityInfo().loadIcon(context.getPackageManager());
this.mFragmentType = AccessibilityServiceFragmentType.BOUNCE; this.mFragmentType = AccessibilityServiceFragmentType.BOUNCE;
@@ -458,15 +452,29 @@ public class AccessibilityButtonChooserActivity extends Activity {
AccessibilityButtonTarget(Context context, @NonNull String id, int labelResId, AccessibilityButtonTarget(Context context, @NonNull String id, int labelResId,
int iconRes, @AccessibilityServiceFragmentType int fragmentType) { int iconRes, @AccessibilityServiceFragmentType int fragmentType) {
this.mId = id; this.mId = id;
this.mType = TargetType.WHITE_LISTING;
this.mChecked = isTargetShortcutUsed(context, mId);
this.mLabel = context.getText(labelResId); this.mLabel = context.getText(labelResId);
this.mDrawable = context.getDrawable(iconRes); this.mDrawable = context.getDrawable(iconRes);
this.mFragmentType = fragmentType; this.mFragmentType = fragmentType;
} }
public void setChecked(boolean checked) {
mChecked = checked;
}
public String getId() { public String getId() {
return mId; return mId;
} }
public int getType() {
return mType;
}
public boolean isChecked() {
return mChecked;
}
public CharSequence getLabel() { public CharSequence getLabel() {
return mLabel; return mLabel;
} }
@@ -519,19 +527,19 @@ public class AccessibilityButtonChooserActivity extends Activity {
} }
private void onLegacyTargetSelected(AccessibilityButtonTarget target) { private void onLegacyTargetSelected(AccessibilityButtonTarget target) {
if (mShortcutType == ACCESSIBILITY_BUTTON) { if (sShortcutType == ACCESSIBILITY_BUTTON) {
final AccessibilityManager ams = getSystemService(AccessibilityManager.class); final AccessibilityManager ams = getSystemService(AccessibilityManager.class);
ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId()); ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId());
} else if (mShortcutType == ACCESSIBILITY_SHORTCUT_KEY) { } else if (sShortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
switchServiceState(target); switchServiceState(target);
} }
} }
private void onInvisibleTargetSelected(AccessibilityButtonTarget target) { private void onInvisibleTargetSelected(AccessibilityButtonTarget target) {
final AccessibilityManager ams = getSystemService(AccessibilityManager.class); final AccessibilityManager ams = getSystemService(AccessibilityManager.class);
if (mShortcutType == ACCESSIBILITY_BUTTON) { if (sShortcutType == ACCESSIBILITY_BUTTON) {
ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId()); ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId());
} else if (mShortcutType == ACCESSIBILITY_SHORTCUT_KEY) { } else if (sShortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
ams.performAccessibilityShortcut(target.getId()); ams.performAccessibilityShortcut(target.getId());
} }
} }
@@ -542,9 +550,9 @@ public class AccessibilityButtonChooserActivity extends Activity {
private void onBounceTargetSelected(AccessibilityButtonTarget target) { private void onBounceTargetSelected(AccessibilityButtonTarget target) {
final AccessibilityManager ams = getSystemService(AccessibilityManager.class); final AccessibilityManager ams = getSystemService(AccessibilityManager.class);
if (mShortcutType == ACCESSIBILITY_BUTTON) { if (sShortcutType == ACCESSIBILITY_BUTTON) {
ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId()); ams.notifyAccessibilityButtonClicked(getDisplayId(), target.getId());
} else if (mShortcutType == ACCESSIBILITY_SHORTCUT_KEY) { } else if (sShortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
ams.performAccessibilityShortcut(target.getId()); ams.performAccessibilityShortcut(target.getId());
} }
} }
@@ -565,66 +573,101 @@ public class AccessibilityButtonChooserActivity extends Activity {
} }
} }
private void onTargetDeleted(AdapterView<?> parent, View view, int position, long id) { private void onTargetChecked(AdapterView<?> parent, View view, int position, long id) {
final AccessibilityButtonTarget target = mTargets.get(position); mCurrentCheckedTarget = mTargets.get(position);
final String componentId = target.getId();
if ((mCurrentCheckedTarget.getType() == TargetType.ACCESSIBILITY_SERVICE)
&& !mCurrentCheckedTarget.isChecked()) {
mEnableDialog = new AlertDialog.Builder(this)
.setView(createEnableDialogContentView(this, mCurrentCheckedTarget,
this::onPermissionAllowButtonClicked,
this::onPermissionDenyButtonClicked))
.create();
mEnableDialog.show();
return;
}
onTargetChecked(mCurrentCheckedTarget, !mCurrentCheckedTarget.isChecked());
}
private void onTargetChecked(AccessibilityButtonTarget target, boolean checked) {
switch (target.getFragmentType()) { switch (target.getFragmentType()) {
case AccessibilityServiceFragmentType.LEGACY: case AccessibilityServiceFragmentType.LEGACY:
onLegacyTargetDeleted(position, componentId); onLegacyTargetChecked(checked);
break; break;
case AccessibilityServiceFragmentType.INVISIBLE: case AccessibilityServiceFragmentType.INVISIBLE:
onInvisibleTargetDeleted(position, componentId); onInvisibleTargetChecked(checked);
break; break;
case AccessibilityServiceFragmentType.INTUITIVE: case AccessibilityServiceFragmentType.INTUITIVE:
onIntuitiveTargetDeleted(position, componentId); onIntuitiveTargetChecked(checked);
break; break;
case AccessibilityServiceFragmentType.BOUNCE: case AccessibilityServiceFragmentType.BOUNCE:
onBounceTargetDeleted(position, componentId); onBounceTargetChecked(checked);
break; break;
default: default:
throw new IllegalStateException("Unexpected fragment type"); throw new IllegalStateException("Unexpected fragment type");
} }
}
private void onLegacyTargetChecked(boolean checked) {
if (sShortcutType == ACCESSIBILITY_BUTTON) {
setServiceEnabled(mCurrentCheckedTarget.getId(), checked);
if (!checked) {
optOutValueFromSettings(this, HARDWARE, mCurrentCheckedTarget.getId());
final String warningText =
getString(R.string.accessibility_uncheck_legacy_item_warning,
mCurrentCheckedTarget.getLabel());
Toast.makeText(this, warningText, Toast.LENGTH_SHORT).show();
}
} else if (sShortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
updateValueToSettings(mCurrentCheckedTarget.getId(), checked);
} else {
throw new IllegalStateException("Unexpected shortcut type");
}
mCurrentCheckedTarget.setChecked(checked);
mTargetAdapter.notifyDataSetChanged();
}
private void onInvisibleTargetChecked(boolean checked) {
final int shortcutTypes = UserShortcutType.SOFTWARE | HARDWARE;
if (!hasValuesInSettings(this, shortcutTypes, mCurrentCheckedTarget.getId())) {
setServiceEnabled(mCurrentCheckedTarget.getId(), checked);
}
updateValueToSettings(mCurrentCheckedTarget.getId(), checked);
mCurrentCheckedTarget.setChecked(checked);
mTargetAdapter.notifyDataSetChanged();
}
private void onIntuitiveTargetChecked(boolean checked) {
updateValueToSettings(mCurrentCheckedTarget.getId(), checked);
mCurrentCheckedTarget.setChecked(checked);
mTargetAdapter.notifyDataSetChanged();
}
private void onBounceTargetChecked(boolean checked) {
updateValueToSettings(mCurrentCheckedTarget.getId(), checked);
mCurrentCheckedTarget.setChecked(checked);
mTargetAdapter.notifyDataSetChanged();
}
private void updateValueToSettings(String componentId, boolean checked) {
if (checked) {
optInValueToSettings(this, mShortcutUserType, componentId);
} else {
optOutValueFromSettings(this, mShortcutUserType, componentId);
}
}
private void onDoneButtonClicked() {
mTargets.clear();
mTargets.addAll(getServiceTargets(this, sShortcutType));
if (mTargets.isEmpty()) { if (mTargets.isEmpty()) {
mAlertDialog.dismiss(); mAlertDialog.dismiss();
} return;
} }
private void onLegacyTargetDeleted(int position, String componentId) {
if (mShortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
optOutValueFromSettings(this, mShortcutUserType, componentId);
mTargets.remove(position);
mTargetAdapter.notifyDataSetChanged();
}
}
private void onInvisibleTargetDeleted(int position, String componentId) {
optOutValueFromSettings(this, mShortcutUserType, componentId);
final int shortcutTypes = UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE;
if (!hasValuesInSettings(this, shortcutTypes, componentId)) {
disableService(componentId);
}
mTargets.remove(position);
mTargetAdapter.notifyDataSetChanged();
}
private void onIntuitiveTargetDeleted(int position, String componentId) {
optOutValueFromSettings(this, mShortcutUserType, componentId);
mTargets.remove(position);
mTargetAdapter.notifyDataSetChanged();
}
private void onBounceTargetDeleted(int position, String componentId) {
optOutValueFromSettings(this, mShortcutUserType, componentId);
mTargets.remove(position);
mTargetAdapter.notifyDataSetChanged();
}
private void onCancelButtonClicked() {
mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.LAUNCH); mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.LAUNCH);
mTargetAdapter.notifyDataSetChanged(); mTargetAdapter.notifyDataSetChanged();
@@ -635,11 +678,13 @@ public class AccessibilityButtonChooserActivity extends Activity {
} }
private void onEditButtonClicked() { private void onEditButtonClicked() {
mTargets.clear();
mTargets.addAll(getInstalledServiceTargets(this));
mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.EDIT); mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.EDIT);
mTargetAdapter.notifyDataSetChanged(); mTargetAdapter.notifyDataSetChanged();
mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText( mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText(
getString(R.string.cancel_accessibility_shortcut_menu_button)); getString(R.string.done_accessibility_shortcut_menu_button));
updateDialogListeners(); updateDialogListeners();
} }
@@ -649,15 +694,78 @@ public class AccessibilityButtonChooserActivity extends Activity {
(mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT); (mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT);
final int selectDialogTitleId = R.string.accessibility_select_shortcut_menu_title; final int selectDialogTitleId = R.string.accessibility_select_shortcut_menu_title;
final int editDialogTitleId = final int editDialogTitleId =
(mShortcutType == ACCESSIBILITY_BUTTON) (sShortcutType == ACCESSIBILITY_BUTTON)
? R.string.accessibility_edit_shortcut_menu_button_title ? R.string.accessibility_edit_shortcut_menu_button_title
: R.string.accessibility_edit_shortcut_menu_volume_title; : R.string.accessibility_edit_shortcut_menu_volume_title;
mAlertDialog.setTitle(getString(isEditMenuMode ? editDialogTitleId : selectDialogTitleId)); mAlertDialog.setTitle(getString(isEditMenuMode ? editDialogTitleId : selectDialogTitleId));
mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener( mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(
isEditMenuMode ? view -> onCancelButtonClicked() : view -> onEditButtonClicked()); isEditMenuMode ? view -> onDoneButtonClicked() : view -> onEditButtonClicked());
mAlertDialog.getListView().setOnItemClickListener( mAlertDialog.getListView().setOnItemClickListener(
isEditMenuMode ? this::onTargetDeleted : this::onTargetSelected); isEditMenuMode ? this::onTargetChecked : this::onTargetSelected);
}
private static boolean isTargetShortcutUsed(@NonNull Context context, String id) {
final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
final List<String> requiredTargets = ams.getAccessibilityShortcutTargets(sShortcutType);
return requiredTargets.contains(id);
}
private void onPermissionAllowButtonClicked(View view) {
if (mCurrentCheckedTarget.getFragmentType() != AccessibilityServiceFragmentType.LEGACY) {
updateValueToSettings(mCurrentCheckedTarget.getId(), /* checked= */ true);
}
onTargetChecked(mCurrentCheckedTarget, /* checked= */ true);
mEnableDialog.dismiss();
}
private void onPermissionDenyButtonClicked(View view) {
mEnableDialog.dismiss();
}
private static View createEnableDialogContentView(Context context,
AccessibilityButtonTarget target, View.OnClickListener allowListener,
View.OnClickListener denyListener) {
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
final View content = inflater.inflate(
R.layout.accessibility_enable_service_encryption_warning, /* root= */ null);
final TextView encryptionWarningView = (TextView) content.findViewById(
R.id.accessibility_encryption_warning);
if (StorageManager.isNonDefaultBlockEncrypted()) {
final String text = context.getString(
R.string.accessibility_enable_service_encryption_warning,
getServiceName(context, target.getLabel()));
encryptionWarningView.setText(text);
encryptionWarningView.setVisibility(View.VISIBLE);
} else {
encryptionWarningView.setVisibility(View.GONE);
}
final ImageView permissionDialogIcon = content.findViewById(
R.id.accessibility_permissionDialog_icon);
permissionDialogIcon.setImageDrawable(target.getDrawable());
final TextView permissionDialogTitle = content.findViewById(
R.id.accessibility_permissionDialog_title);
permissionDialogTitle.setText(context.getString(R.string.accessibility_enable_service_title,
getServiceName(context, target.getLabel())));
final Button permissionAllowButton = content.findViewById(
R.id.accessibility_permission_enable_allow_button);
final Button permissionDenyButton = content.findViewById(
R.id.accessibility_permission_enable_deny_button);
permissionAllowButton.setOnClickListener(allowListener);
permissionDenyButton.setOnClickListener(denyListener);
return content;
}
// Gets the service name and bidi wrap it to protect from bidi side effects.
private static CharSequence getServiceName(Context context, CharSequence label) {
final Locale locale = context.getResources().getConfiguration().getLocales().get(0);
return BidiFormatter.getInstance(locale).unicodeWrap(label);
} }
} }

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2020 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M23,5.5V20c0,2.2 -1.8,4 -4,4h-7.3c-1.08,0 -2.1,-0.43 -2.85,-1.19L1,14.83c0,0 1.26,-1.23 1.3,-1.25c0.22,-0.19 0.49,-0.29 0.79,-0.29c0.22,0 0.42,0.06 0.6,0.16C3.73,13.46 8,15.91 8,15.91V4c0,-0.83 0.67,-1.5 1.5,-1.5S11,3.17 11,4v7h1V1.5C12,0.67 12.67,0 13.5,0S15,0.67 15,1.5V11h1V2.5C16,1.67 16.67,1 17.5,1S19,1.67 19,2.5V11h1V5.5C20,4.67 20.67,4 21.5,4S23,4.67 23,5.5z"
android:fillColor="#FFFFFF"/>
</vector>

View File

@@ -21,6 +21,6 @@
android:viewportHeight="24" android:viewportHeight="24"
android:tint="?attr/colorControlNormal"> android:tint="?attr/colorControlNormal">
<path <path
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"
android:fillColor="#FFFFFF"/> android:fillColor="#FFFFFF"/>
</vector> </vector>

View File

@@ -21,10 +21,17 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:padding="16dp">
<CheckBox
android:id="@+id/accessibility_button_target_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="16dp" android:background="@null"
android:paddingTop="12dp" android:clickable="false"
android:paddingBottom="12dp"> android:focusable="false"
android:visibility="gone"/>
<ImageView <ImageView
android:id="@+id/accessibility_button_target_icon" android:id="@+id/accessibility_button_target_icon"
@@ -36,31 +43,18 @@
android:id="@+id/accessibility_button_target_label" android:id="@+id/accessibility_button_target_label"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="14dp" android:layout_marginStart="16dp"
android:layout_weight="1" android:layout_weight="1"
android:textSize="20sp" android:textSize="20sp"
android:textColor="?attr/textColorPrimary" android:textColor="?attr/textColorPrimary"
android:fontFamily="sans-serif-medium"/> android:fontFamily="sans-serif-medium"/>
<FrameLayout <Switch
android:id="@+id/accessibility_button_target_item_container" android:id="@+id/accessibility_button_target_switch_item"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minWidth="56dp">
<ImageView
android:id="@+id/accessibility_button_target_view_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<Switch android:id="@+id/accessibility_button_target_switch_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null" android:background="@null"
android:clickable="false" android:clickable="false"
android:focusable="false"/> android:focusable="false"/>
</FrameLayout>
</LinearLayout> </LinearLayout>

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textDirection="locale"
android:scrollbarStyle="outsideOverlay">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/accessibility_permissionDialog_icon"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/accessibility_permissionDialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="google-sans-medium"/>
<TextView
android:id="@+id/accessibility_encryption_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dip"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/accessibility_permissionDialog_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:text="@string/accessibility_service_warning_description"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="sans-serif"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/accessibility_controlScreen_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginRight="12dp"
android:src="@android:drawable/ic_visibility"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/accessibility_controlScreen_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/accessibility_service_screen_control_title"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="sans-serif"/>
</LinearLayout>
<TextView
android:id="@+id/accessibility_controlScreen_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:paddingStart="30dp"
android:text="@string/accessibility_service_screen_control_description"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:fontFamily="sans-serif"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/accessibility_performAction_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginEnd="12dp"
android:src="@android:drawable/ic_pan_tool"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/accessibility_performAction_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/accessibility_service_action_perform_title"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="sans-serif"/>
</LinearLayout>
<TextView
android:id="@+id/accessibility_performAction_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:paddingStart="30dp"
android:text="@string/accessibility_service_action_perform_description"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:fontFamily="sans-serif" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/chooser_row_divider"/>
<Button
android:id="@+id/accessibility_permission_enable_allow_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?android:attr/selectableItemBackground"
android:text="@string/accessibility_dialog_button_allow"
style="?attr/buttonBarPositiveButtonStyle"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/chooser_row_divider"/>
<Button
android:id="@+id/accessibility_permission_enable_deny_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?android:attr/selectableItemBackground"
android:text="@string/accessibility_dialog_button_deny"
style="?attr/buttonBarPositiveButtonStyle"/>
</LinearLayout>
</ScrollView>

View File

@@ -4403,27 +4403,72 @@
accessibility feature. accessibility feature.
</string> </string>
<!-- Title for a warning about security implications of enabling an accessibility
service. [CHAR LIMIT=NONE] -->
<string name="accessibility_enable_service_title">Allow
<xliff:g id="service" example="TalkBack">%1$s</xliff:g> to have full control of your
device?</string>
<!-- Warning that the device data will not be encrypted with password or PIN if
enabling an accessibility service and there is a secure lock setup. [CHAR LIMIT=NONE] -->
<string name="accessibility_enable_service_encryption_warning">If you turn on
<xliff:g id="service" example="TalkBack">%1$s</xliff:g>, your device won’t use your screen
lock to enhance data encryption.
</string>
<!-- Warning description that explains that it's appropriate for accessibility
services to have full control to help users with accessibility needs. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_warning_description">Full control is appropriate for apps
that help you with accessibility needs, but not for most apps.
</string>
<!-- Title for the screen control in accessibility dialog. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_screen_control_title">View and control screen</string>
<!-- Description for the screen control in accessibility dialog. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_screen_control_description">It can read all content on the
screen and display content over other apps.
</string>
<!-- Title for the action perform in accessibility dialog. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_action_perform_title">View and perform actions</string>
<!-- Description for the action perform in accessibility dialog. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_action_perform_description">It can track your interactions
with an app or a hardware sensor, and interact with apps on your behalf.
</string>
<!-- String for the allow button in accessibility permission dialog. [CHAR LIMIT=10] -->
<string name="accessibility_dialog_button_allow">Allow</string>
<!-- String for the deny button in accessibility permission dialog. [CHAR LIMIT=10] -->
<string name="accessibility_dialog_button_deny">Deny</string>
<!-- Title for accessibility select shortcut menu dialog. [CHAR LIMIT=100] --> <!-- Title for accessibility select shortcut menu dialog. [CHAR LIMIT=100] -->
<string name="accessibility_select_shortcut_menu_title">Tap the accessibility app you want to use</string> <string name="accessibility_select_shortcut_menu_title">Tap a feature to start using it:</string>
<!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered <!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
from accessibility button. [CHAR LIMIT=100] --> from accessibility button. [CHAR LIMIT=100] -->
<string name="accessibility_edit_shortcut_menu_button_title">Choose apps you want to use with <string name="accessibility_edit_shortcut_menu_button_title">Choose apps to use with the
accessibility button accessibility button
</string> </string>
<!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered <!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
from volume key shortcut. [CHAR LIMIT=100] --> from volume key shortcut. [CHAR LIMIT=100] -->
<string name="accessibility_edit_shortcut_menu_volume_title">Choose apps you want to use with <string name="accessibility_edit_shortcut_menu_volume_title">Choose apps to use with the
volume key shortcut volume key shortcut
</string> </string>
<!-- Text for showing the warning to user when uncheck the legacy app item in the accessibility
shortcut menu, user can aware the service to be disabled. [CHAR LIMIT=100] -->
<string name="accessibility_uncheck_legacy_item_warning">
<xliff:g id="service_name" example="TalkBack">%s</xliff:g> has been turned off</string>
<!-- Text in button that edit the accessibility shortcut menu, user can delete <!-- Text in button that edit the accessibility shortcut menu, user can delete
any service item in the menu list. [CHAR LIMIT=100] --> any service item in the menu list. [CHAR LIMIT=100] -->
<string name="edit_accessibility_shortcut_menu_button">Edit shortcuts</string> <string name="edit_accessibility_shortcut_menu_button">Edit shortcuts</string>
<!-- Text in button that cancel the accessibility shortcut menu changed status. [CHAR LIMIT=100] --> <!-- Text in button that complete the accessibility shortcut menu changed status. [CHAR LIMIT=100] -->
<string name="cancel_accessibility_shortcut_menu_button">Cancel</string> <string name="done_accessibility_shortcut_menu_button">Done</string>
<!-- Text in button that turns off the accessibility shortcut --> <!-- Text in button that turns off the accessibility shortcut -->
<string name="disable_accessibility_shortcut">Turn off Shortcut</string> <string name="disable_accessibility_shortcut">Turn off Shortcut</string>

View File

@@ -3240,24 +3240,31 @@
<java-symbol type="string" name="accessibility_select_shortcut_menu_title" /> <java-symbol type="string" name="accessibility_select_shortcut_menu_title" />
<java-symbol type="string" name="accessibility_edit_shortcut_menu_button_title" /> <java-symbol type="string" name="accessibility_edit_shortcut_menu_button_title" />
<java-symbol type="string" name="accessibility_edit_shortcut_menu_volume_title" /> <java-symbol type="string" name="accessibility_edit_shortcut_menu_volume_title" />
<java-symbol type="string" name="accessibility_uncheck_legacy_item_warning" />
<java-symbol type="layout" name="accessibility_enable_service_encryption_warning" />
<java-symbol type="id" name="accessibility_permissionDialog_icon" />
<java-symbol type="id" name="accessibility_permissionDialog_title" />
<java-symbol type="id" name="accessibility_encryption_warning" />
<java-symbol type="id" name="accessibility_permission_enable_allow_button" />
<java-symbol type="id" name="accessibility_permission_enable_deny_button" />
<java-symbol type="string" name="accessibility_enable_service_title" />
<java-symbol type="string" name="accessibility_enable_service_encryption_warning" />
<!-- Accessibility Button --> <!-- Accessibility Button -->
<java-symbol type="layout" name="accessibility_button_chooser_item" /> <java-symbol type="layout" name="accessibility_button_chooser_item" />
<java-symbol type="id" name="accessibility_button_target_checkbox" />
<java-symbol type="id" name="accessibility_button_target_icon" /> <java-symbol type="id" name="accessibility_button_target_icon" />
<java-symbol type="id" name="accessibility_button_target_label" /> <java-symbol type="id" name="accessibility_button_target_label" />
<java-symbol type="id" name="accessibility_button_target_item_container" />
<java-symbol type="id" name="accessibility_button_target_view_item" />
<java-symbol type="id" name="accessibility_button_target_switch_item" /> <java-symbol type="id" name="accessibility_button_target_switch_item" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" /> <java-symbol type="string" name="accessibility_magnification_chooser_text" />
<java-symbol type="string" name="edit_accessibility_shortcut_menu_button" /> <java-symbol type="string" name="edit_accessibility_shortcut_menu_button" />
<java-symbol type="string" name="cancel_accessibility_shortcut_menu_button" /> <java-symbol type="string" name="done_accessibility_shortcut_menu_button" />
<java-symbol type="drawable" name="ic_accessibility_color_inversion" /> <java-symbol type="drawable" name="ic_accessibility_color_inversion" />
<java-symbol type="drawable" name="ic_accessibility_color_correction" /> <java-symbol type="drawable" name="ic_accessibility_color_correction" />
<java-symbol type="drawable" name="ic_accessibility_magnification" /> <java-symbol type="drawable" name="ic_accessibility_magnification" />
<java-symbol type="drawable" name="ic_delete_item" />
<!-- com.android.internal.widget.RecyclerView --> <!-- com.android.internal.widget.RecyclerView -->
<java-symbol type="id" name="item_touch_helper_previous_elevation"/> <java-symbol type="id" name="item_touch_helper_previous_elevation"/>
<java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/> <java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/>