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

Commit 71d7b807 authored by Rasheed Lewis's avatar Rasheed Lewis Committed by Automerger Merge Worker
Browse files

Merge "Add Start Activity API for TileServices" into tm-qpr-dev am: b9b84486 am: 281d3ac8

parents c284347b 281d3ac8
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