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

Commit b9b84486 authored by Rasheed Lewis's avatar Rasheed Lewis Committed by Android (Google) Code Review
Browse files

Merge "Add Start Activity API for TileServices" into tm-qpr-dev

parents 258944c4 e00edd6d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package android.service.quicksettings;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.graphics.drawable.Icon;
import android.service.quicksettings.Tile;
@@ -29,10 +30,10 @@ interface IQSService {
            String contentDescription);
    void onShowDialog(in IBinder tile);
    void onStartActivity(in IBinder tile);
    void startActivity(in IBinder tile, in PendingIntent pendingIntent);
    boolean isLocked();
    boolean isSecure();
    void startUnlockAndRun(in IBinder tile);

    void onDialogHidden(in IBinder tile);
    void onStartSuccessful(in IBinder tile);
}
+41 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.service.quicksettings;

import android.annotation.Nullable;
import android.app.PendingIntent;
import android.graphics.drawable.Icon;
import android.os.IBinder;
import android.os.Parcel;
@@ -66,6 +67,7 @@ public final class Tile implements Parcelable {
    private CharSequence mSubtitle;
    private CharSequence mContentDescription;
    private CharSequence mStateDescription;
    private PendingIntent mPendingIntent;
    // Default to inactive until clients of the new API can update.
    private int mState = STATE_INACTIVE;

@@ -223,6 +225,34 @@ public final class Tile implements Parcelable {
        }
    }

    /**
     * Gets the Activity {@link PendingIntent} to be launched when the tile is clicked.
     * @hide
     */
    @Nullable
    public PendingIntent getActivityLaunchForClick() {
        return mPendingIntent;
    }

    /**
     * Sets an Activity {@link PendingIntent} to be launched when the tile is clicked.
     *
     * The last value set here will be launched when the user clicks in the tile, instead of
     * forwarding the `onClick` message to the {@link TileService}. Set to {@code null} to handle
     * the `onClick` in the `TileService`
     * (This is the default behavior if this method is never called.)
     * @param pendingIntent a PendingIntent for an activity to be launched onclick, or {@code null}
     *                      to handle the clicks in the `TileService`.
     * @hide
     */
    public void setActivityLaunchForClick(@Nullable PendingIntent pendingIntent) {
        if (pendingIntent != null && !pendingIntent.isActivity()) {
            throw new IllegalArgumentException();
        } else {
            mPendingIntent = pendingIntent;
        }
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (mIcon != null) {
@@ -231,6 +261,12 @@ public final class Tile implements Parcelable {
        } else {
            dest.writeByte((byte) 0);
        }
        if (mPendingIntent != null) {
            dest.writeByte((byte) 1);
            mPendingIntent.writeToParcel(dest, flags);
        } else {
            dest.writeByte((byte) 0);
        }
        dest.writeInt(mState);
        TextUtils.writeToParcel(mLabel, dest, flags);
        TextUtils.writeToParcel(mSubtitle, dest, flags);
@@ -244,6 +280,11 @@ public final class Tile implements Parcelable {
        } else {
            mIcon = null;
        }
        if (source.readByte() != 0) {
            mPendingIntent = PendingIntent.CREATOR.createFromParcel(source);
        } else {
            mPendingIntent = null;
        }
        mState = source.readInt();
        mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
        mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+15 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Dialog;
import android.app.PendingIntent;
import android.app.Service;
import android.app.StatusBarManager;
import android.content.ComponentName;
@@ -335,6 +336,20 @@ public class TileService extends Service {
        }
    }

    /**
     * Starts an {@link android.app.Activity}.
     * Will collapse Quick Settings after launching.
     *
     * @param pendingIntent A PendingIntent for an Activity to be launched immediately.
     * @hide
     */
    public void startActivityAndCollapse(PendingIntent pendingIntent) {
        try {
            mService.startActivity(mTileToken, pendingIntent);
        } catch (RemoteException e) {
        }
    }

    /**
     * Gets the {@link Tile} for this service.
     * <p/>
+39 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.qs.external;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -51,6 +52,7 @@ import androidx.annotation.WorkerThread;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -92,6 +94,8 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
    private android.graphics.drawable.Icon mDefaultIcon;
    @Nullable
    private CharSequence mDefaultLabel;
    @Nullable
    private View mViewClicked;

    private final Context mUserContext;

@@ -229,7 +233,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener

    /**
     * Custom tile is considered available if there is a default icon (obtained from PM).
     *
     * <p>
     * It will return {@code true} before initialization, so tiles are not destroyed prematurely.
     */
    @Override
@@ -262,6 +266,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener

    /**
     * Update state of {@link this#mTile} from a remote {@link TileService}.
     *
     * @param tile tile populated with state to apply
     */
    public void updateTileState(Tile tile) {
@@ -293,6 +298,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
        if (tile.getStateDescription() != null || overwriteNulls) {
            mTile.setStateDescription(tile.getStateDescription());
        }
        mTile.setActivityLaunchForClick(tile.getActivityLaunchForClick());
        mTile.setState(tile.getState());
    }

@@ -324,6 +330,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
                    mService.onStartListening();
                }
            } else {
                mViewClicked = null;
                mService.onStopListening();
                if (mIsTokenGranted && !mIsShowingDialog) {
                    try {
@@ -388,6 +395,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
        if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
            return;
        }
        mViewClicked = view;
        try {
            if (DEBUG) Log.d(TAG, "Adding token");
            mWindowManager.addWindowToken(mToken, TYPE_QS_DIALOG, DEFAULT_DISPLAY,
@@ -400,7 +408,12 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
                mServiceManager.setBindRequested(true);
                mService.onStartListening();
            }

            if (mTile.getActivityLaunchForClick() != null) {
                startActivityAndCollapse(mTile.getActivityLaunchForClick());
            } else {
                mService.onClick(mToken);
            }
        } catch (RemoteException e) {
            // Called through wrapper, won't happen here.
        }
@@ -483,6 +496,27 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
        });
    }

    /**
     * Starts an {@link android.app.Activity}
     * @param pendingIntent A PendingIntent for an Activity to be launched immediately.
     */
    public void startActivityAndCollapse(PendingIntent pendingIntent) {
        if (!pendingIntent.isActivity()) {
            Log.i(TAG, "Intent not for activity.");
        } else if (!mIsTokenGranted) {
            Log.i(TAG, "Launching activity before click");
        } else {
            Log.i(TAG, "The activity is starting");
            ActivityLaunchAnimator.Controller controller = mViewClicked == null
                    ? null
                    : ActivityLaunchAnimator.Controller.fromView(mViewClicked, 0);
            mUiHandler.post(() ->
                    mActivityStarter.startPendingIntentDismissingKeyguard(
                            pendingIntent, null, controller)
            );
        }
    }

    public static String toSpec(ComponentName name) {
        return PREFIX + name.flattenToShortString() + ")";
    }
+16 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.systemui.qs.external;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -32,6 +33,7 @@ import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -275,6 +277,19 @@ public class TileServices extends IQSService.Stub {
        }
    }

    @Override
    public void startActivity(IBinder token, PendingIntent pendingIntent) {
        startActivity(getTileForToken(token), pendingIntent);
    }

    @VisibleForTesting
    protected void startActivity(CustomTile customTile, PendingIntent pendingIntent) {
        if (customTile != null) {
            verifyCaller(customTile);
            customTile.startActivityAndCollapse(pendingIntent);
        }
    }

    @Override
    public void updateStatusIcon(IBinder token, Icon icon, String contentDescription) {
        CustomTile customTile = getTileForToken(token);
@@ -336,7 +351,7 @@ public class TileServices extends IQSService.Stub {
    }

    @Nullable
    private CustomTile getTileForToken(IBinder token) {
    public CustomTile getTileForToken(IBinder token) {
        synchronized (mServices) {
            return mTokenMap.get(token);
        }
Loading