Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e8fd460 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Target selection for Accessibility button"

parents bf4d8d12 5e8b980c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -5510,6 +5510,16 @@ public final class Settings {
        public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE =
                "accessibility_shortcut_target_service";

        /**
         * Setting specifying the accessibility service or feature to be toggled via the
         * accessibility button in the navigation bar. This is either a flattened
         * {@link ComponentName} or the class name of a system class implementing a supported
         * accessibility feature.
         * @hide
         */
        public static final String ACCESSIBILITY_BUTTON_TARGET_COMPONENT =
                "accessibility_button_target_component";

        /**
         * If touch exploration is enabled.
         */
@@ -6997,6 +7007,7 @@ public final class Settings {
            TOUCH_EXPLORATION_ENABLED,
            ACCESSIBILITY_ENABLED,
            ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
            ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
            ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
            ACCESSIBILITY_SHORTCUT_ENABLED,
            ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+17 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.Manifest;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -97,6 +98,22 @@ public final class AccessibilityManager {
    /** @hide */
    public static final int AUTOCLICK_DELAY_DEFAULT = 600;

    /**
     * Activity action: Launch UI to manage which accessibility service or feature is assigned
     * to the navigation bar Accessibility button.
     * <p>
     * Input: Nothing.
     * </p>
     * <p>
     * Output: Nothing.
     * </p>
     *
     * @hide
     */
    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON =
            "android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON";

    static final Object sInstanceSync = new Object();

    private static AccessibilityManager sInstance;
+174 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.internal.app;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.internal.R;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Activity used to display and persist a service or feature target for the Accessibility button.
 */
public class AccessibilityButtonChooserActivity extends Activity {

    private static final String MAGNIFICATION_COMPONENT_ID =
            "com.android.server.accessibility.MagnificationController";

    private AccessibilityButtonTarget mMagnificationTarget = null;

    private List<AccessibilityButtonTarget> mTargets = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.accessibility_button_chooser);

        String component = Settings.Secure.getString(getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
        if (TextUtils.isEmpty(component)) {
            TextView prompt = (TextView) findViewById(R.id.accessibility_button_prompt);
            prompt.setVisibility(View.VISIBLE);
        }

        mMagnificationTarget = new AccessibilityButtonTarget(this, MAGNIFICATION_COMPONENT_ID,
                R.string.accessibility_magnification_chooser_text,
                R.drawable.resolver_icon_placeholder);

        mTargets = getServiceAccessibilityButtonTargets(this);
        if (Settings.Secure.getInt(getContentResolver(),
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1) {
            mTargets.add(mMagnificationTarget);
        }

        if (mTargets.size() < 2) {
            // Why are we here?
            finish();
        }

        GridView gridview = (GridView) findViewById(R.id.accessibility_button_chooser_grid);
        gridview.setAdapter(new TargetAdapter());
        gridview.setOnItemClickListener((parent, view, position, id) -> {
            onTargetSelected(mTargets.get(position));
        });
    }

    private static List<AccessibilityButtonTarget> getServiceAccessibilityButtonTargets(
            @NonNull Context context) {
        AccessibilityManager ams = (AccessibilityManager) context.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> services = ams.getEnabledAccessibilityServiceList(
                AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
        if (services == null) {
            return Collections.emptyList();
        }

        ArrayList<AccessibilityButtonTarget> targets = new ArrayList<>(services.size());
        for (AccessibilityServiceInfo info : services) {
            if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) {
                targets.add(new AccessibilityButtonTarget(context, info));
            }
        }

        return targets;
    }

    private void onTargetSelected(AccessibilityButtonTarget target) {
        Settings.Secure.putString(getContentResolver(),
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, target.getId());
        finish();
    }

    private class TargetAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return mTargets.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = AccessibilityButtonChooserActivity.this.getLayoutInflater();
            View root = inflater.inflate(R.layout.accessibility_button_chooser_item, parent, false);
            final AccessibilityButtonTarget target = mTargets.get(position);
            ImageView iconView = root.findViewById(R.id.accessibility_button_target_icon);
            TextView labelView = root.findViewById(R.id.accessibility_button_target_label);
            iconView.setImageDrawable(target.getDrawable());
            labelView.setText(target.getLabel());
            return root;
        }
    }

    private static class AccessibilityButtonTarget {
        public String mId;
        public CharSequence mLabel;
        public Drawable mDrawable;

        public AccessibilityButtonTarget(@NonNull Context context,
                @NonNull AccessibilityServiceInfo serviceInfo) {
            this.mId = serviceInfo.getComponentName().flattenToString();
            this.mLabel = serviceInfo.getResolveInfo().loadLabel(context.getPackageManager());
            this.mDrawable = serviceInfo.getResolveInfo().loadIcon(context.getPackageManager());
        }

        public AccessibilityButtonTarget(Context context, @NonNull String id, int labelResId,
                int iconRes) {
            this.mId = id;
            this.mLabel = context.getText(labelResId);
            this.mDrawable = context.getDrawable(iconRes);
        }

        public String getId() {
            return mId;
        }

        public CharSequence getLabel() {
            return mLabel;
        }

        public Drawable getDrawable() {
            return mDrawable;
        }
    }
}
 No newline at end of file
+13 −0
Original line number Diff line number Diff line
@@ -3344,6 +3344,19 @@
                <category android:name="android.intent.category.VOICE" />
            </intent-filter>
        </activity>
        <activity android:name="com.android.internal.app.AccessibilityButtonChooserActivity"
                  android:theme="@style/Theme.DeviceDefault.Resolver"
                  android:finishOnCloseSystemDialogs="true"
                  android:excludeFromRecents="true"
                  android:documentLaunchMode="never"
                  android:relinquishTaskIdentity="true"
                  android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
                  android:process=":ui">
            <intent-filter>
                <action android:name="android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity android:name="com.android.internal.app.IntentForwarderActivity"
                android:finishOnCloseSystemDialogs="true"
                android:theme="@style/Theme.NoDisplay"
+76 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2017, 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.
*/
-->
<com.android.internal.widget.ResolverDrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:maxWidth="@dimen/resolver_max_width"
    android:maxCollapsedHeight="256dp"
    android:maxCollapsedHeightSmall="56dp"
    android:id="@id/contentPanel">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="?attr/colorBackground"
        android:paddingTop="8dp"
        android:paddingBottom="8dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="56dp"
            android:textAppearance="?attr/textAppearanceMedium"
            android:text="@string/accessibility_button_prompt_text"
            android:gravity="start|center_vertical"
            android:layout_alignParentStart="true"
            android:paddingStart="?attr/dialogPreferredPadding"
            android:paddingEnd="?attr/dialogPreferredPadding"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"/>

        <GridView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/accessibility_button_chooser_grid"
            android:columnWidth="90dp"
            android:numColumns="auto_fit"
            android:verticalSpacing="10dp"
            android:horizontalSpacing="10dp"
            android:stretchMode="columnWidth"
            android:paddingStart="?attr/dialogPreferredPadding"
            android:paddingEnd="?attr/dialogPreferredPadding"
            android:gravity="center"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/accessibility_button_prompt"
            android:layout_alwaysShow="true"
            android:textAppearance="?attr/textAppearanceMedium"
            android:text="@string/accessibility_button_instructional_text"
            android:gravity="start|center_vertical"
            android:paddingStart="?attr/dialogPreferredPadding"
            android:paddingEnd="?attr/dialogPreferredPadding"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            android:visibility="gone"/>
    </LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
Loading