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

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

Merge "Add hooks for custom global actions handling without a status bar."

parents f335c50f 2decbf7a
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.globalactions;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/** What each item in the global actions dialog must be able to support. */
public interface Action {
    /** @return Text that will be announced when dialog is created. {@code null} for none. */
    CharSequence getLabelForAccessibility(Context context);

    /** Create the view that represents this action. */
    View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);

    /** Called when the action is selected by the user. */
    void onPress();

    /** @return whether this action should appear in the dialog when the keygaurd is showing. */
    boolean showDuringKeyguard();

    /** @return whether this action should appear in the dialog before the device is provisioned. */
    boolean showBeforeProvisioning();

    /** @return {@code true} if the action is enabled for user interaction. */
    boolean isEnabled();
}
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.globalactions;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.function.BooleanSupplier;
import java.util.List;

/**
 * The adapter used for the list within the global actions dialog, taking into account whether the
 * keyguard is showing via {@link LegacyGlobalActions#mKeyguardShowing} and whether the device is
 * provisioned via {@link LegacyGlobalActions#mDeviceProvisioned}.
 */
public class ActionsAdapter extends BaseAdapter {
    private final Context mContext;
    private final List<Action> mItems;
    private final BooleanSupplier mDeviceProvisioned;
    private final BooleanSupplier mKeyguardShowing;

    public ActionsAdapter(Context context, List<Action> items,
            BooleanSupplier deviceProvisioned, BooleanSupplier keyguardShowing) {
        mContext = context;
        mItems = items;
        mDeviceProvisioned = deviceProvisioned;
        mKeyguardShowing = keyguardShowing;
    }

    @Override
    public int getCount() {
        final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
        final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();
        int count = 0;

        for (int i = 0; i < mItems.size(); i++) {
            final Action action = mItems.get(i);

            if (keyguardShowing && !action.showDuringKeyguard()) {
                continue;
            }
            if (!deviceProvisioned && !action.showBeforeProvisioning()) {
                continue;
            }
            count++;
        }
        return count;
    }

    @Override
    public boolean isEnabled(int position) {
        return getItem(position).isEnabled();
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public Action getItem(int position) {
        final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
        final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();

        int filteredPos = 0;
        for (int i = 0; i < mItems.size(); i++) {
            final Action action = mItems.get(i);
            if (keyguardShowing && !action.showDuringKeyguard()) {
                continue;
            }
            if (!deviceProvisioned && !action.showBeforeProvisioning()) {
                continue;
            }
            if (filteredPos == position) {
                return action;
            }
            filteredPos++;
        }

        throw new IllegalArgumentException("position " + position
                + " out of range of showable actions"
                + ", filtered count=" + getCount()
                + ", keyguardshowing=" + keyguardShowing
                + ", provisioned=" + deviceProvisioned);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Action action = getItem(position);
        return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
    }
}
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.globalactions;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.accessibility.AccessibilityEvent;
import android.view.KeyEvent;
import android.widget.ListView;
import com.android.internal.app.AlertController;

/** A dialog that lists the given Action items to be user selectable. */
public final class ActionsDialog extends Dialog implements DialogInterface {
    private final Context mContext;
    private final AlertController mAlert;
    private final ActionsAdapter mAdapter;

    public ActionsDialog(Context context, AlertController.AlertParams params) {
        super(context, getDialogTheme(context));
        mContext = getContext();
        mAlert = AlertController.create(mContext, this, getWindow());
        mAdapter = (ActionsAdapter) params.mAdapter;
        params.apply(mAlert);
    }

    private static int getDialogTheme(Context context) {
        TypedValue outValue = new TypedValue();
        context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
                outValue, true);
        return outValue.resourceId;
    }

    @Override
    protected void onStart() {
        super.setCanceledOnTouchOutside(true);
        super.onStart();
    }

    public ListView getListView() {
        return mAlert.getListView();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAlert.installContent();
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            for (int i = 0; i < mAdapter.getCount(); ++i) {
                CharSequence label =
                        mAdapter.getItem(i).getLabelForAccessibility(getContext());
                if (label != null) {
                    event.getText().add(label);
                }
            }
        }
        return super.dispatchPopulateAccessibilityEvent(event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (mAlert.onKeyDown(keyCode, event)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (mAlert.onKeyUp(keyCode, event)) {
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.globalactions;

/** An action that also supports long press. */
public interface LongPressAction extends Action {
    boolean onLongPress();
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.globalactions;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;

/** A single press action maintains no state, just responds to a press and takes an action. */
public abstract class SinglePressAction implements Action {
    private final int mIconResId;
    private final Drawable mIcon;
    private final int mMessageResId;
    private final CharSequence mMessage;

    protected SinglePressAction(int iconResId, int messageResId) {
        mIconResId = iconResId;
        mMessageResId = messageResId;
        mMessage = null;
        mIcon = null;
    }

    protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
        mIconResId = iconResId;
        mMessageResId = 0;
        mMessage = message;
        mIcon = icon;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public String getStatus() {
        return null;
    }

    @Override
    abstract public void onPress();

    @Override
    public CharSequence getLabelForAccessibility(Context context) {
        if (mMessage != null) {
            return mMessage;
        } else {
            return context.getString(mMessageResId);
        }
    }

    @Override
    public View create(
            Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
        View v = inflater.inflate(R.layout.global_actions_item, parent, false);

        ImageView icon = v.findViewById(R.id.icon);
        TextView messageView = v.findViewById(R.id.message);

        TextView statusView = v.findViewById(R.id.status);
        final String status = getStatus();
        if (!TextUtils.isEmpty(status)) {
            statusView.setText(status);
        } else {
            statusView.setVisibility(View.GONE);
        }
        if (mIcon != null) {
            icon.setImageDrawable(mIcon);
            icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
        } else if (mIconResId != 0) {
            icon.setImageDrawable(context.getDrawable(mIconResId));
        }
        if (mMessage != null) {
            messageView.setText(mMessage);
        } else {
            messageView.setText(mMessageResId);
        }

        return v;
    }
}
Loading