Using a proxy activity for startActivityForResult

This ensures that the home task is never blocked by a different task

Bug: 74500048
Change-Id: I01fd26f1d6242e39b2d8fabac5e064b748aebe62
This commit is contained in:
Sunny Goyal
2019-05-14 15:23:48 -07:00
parent 7daf892f66
commit dedda05568
8 changed files with 314 additions and 10 deletions

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 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.launcher3.proxy;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.util.Log;
public class ProxyActivityStarter extends Activity {
private static final String TAG = "ProxyActivityStarter";
public static final String EXTRA_PARAMS = "start-activity-params";
private StartActivityParams mParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVisible(false);
mParams = getIntent().getParcelableExtra(EXTRA_PARAMS);
if (mParams == null) {
Log.d(TAG, "Proxy activity started without params");
finishAndRemoveTask();
return;
}
if (savedInstanceState != null) {
// Already started the activity. Just wait for the result.
return;
}
if (mParams.intent != null) {
startActivityForResult(mParams.intent, mParams.requestCode, mParams.options);
return;
} else if (mParams.intentSender != null) {
try {
startIntentSenderForResult(mParams.intentSender, mParams.requestCode,
mParams.fillInIntent, mParams.flagsMask, mParams.flagsValues,
mParams.extraFlags,
mParams.options);
return;
} catch (SendIntentException e) {
mParams.deliverResult(this, RESULT_CANCELED, null);
}
}
finishAndRemoveTask();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == mParams.requestCode) {
mParams.deliverResult(this, resultCode, data);
}
finishAndRemoveTask();
}
public static Intent getLaunchIntent(Context context, StartActivityParams params) {
return new Intent(context, ProxyActivityStarter.class)
.putExtra(EXTRA_PARAMS, params)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2019 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.launcher3.proxy;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
public class StartActivityParams implements Parcelable {
private static final String TAG = "StartActivityParams";
private final PendingIntent mCallback;
public final int requestCode;
public Intent intent;
public IntentSender intentSender;
public Intent fillInIntent;
public int flagsMask;
public int flagsValues;
public int extraFlags;
public Bundle options;
public StartActivityParams(Activity activity, int requestCode) {
mCallback = activity.createPendingResult(requestCode, new Intent(),
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
this.requestCode = requestCode;
}
private StartActivityParams(Parcel parcel) {
mCallback = parcel.readTypedObject(PendingIntent.CREATOR);
requestCode = parcel.readInt();
intent = parcel.readTypedObject(Intent.CREATOR);
intentSender = parcel.readTypedObject(IntentSender.CREATOR);
fillInIntent = parcel.readTypedObject(Intent.CREATOR);
flagsMask = parcel.readInt();
flagsValues = parcel.readInt();
extraFlags = parcel.readInt();
options = parcel.readBundle();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedObject(mCallback, flags);
parcel.writeInt(requestCode);
parcel.writeTypedObject(intent, flags);
parcel.writeTypedObject(intentSender, flags);
parcel.writeTypedObject(fillInIntent, flags);
parcel.writeInt(flagsMask);
parcel.writeInt(flagsValues);
parcel.writeInt(extraFlags);
parcel.writeBundle(options);
}
public void deliverResult(Context context, int resultCode, Intent data) {
try {
mCallback.send(context, resultCode, data);
} catch (CanceledException e) {
Log.e(TAG, "Unable to send back result", e);
}
}
public static final Parcelable.Creator<StartActivityParams> CREATOR =
new Parcelable.Creator<StartActivityParams>() {
public StartActivityParams createFromParcel(Parcel source) {
return new StartActivityParams(source);
}
public StartActivityParams[] newArray(int size) {
return new StartActivityParams[size];
}
};
}

View File

@@ -16,6 +16,8 @@
package com.android.launcher3.uioverrides;
import static android.app.Activity.RESULT_CANCELED;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -31,6 +33,9 @@ import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.util.Base64;
@@ -43,6 +48,8 @@ import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SysUINavigationMode;
@@ -192,6 +199,40 @@ public class UiFactory extends RecentsUiFactory {
return true;
}
public static boolean startIntentSenderForResult(Activity activity, IntentSender intent,
int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
Bundle options) {
StartActivityParams params = new StartActivityParams(activity, requestCode);
params.intentSender = intent;
params.fillInIntent = fillInIntent;
params.flagsMask = flagsMask;
params.flagsValues = flagsValues;
params.extraFlags = extraFlags;
params.options = options;
((Context) activity).startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
return true;
}
public static boolean startActivityForResult(Activity activity, Intent intent, int requestCode,
Bundle options) {
StartActivityParams params = new StartActivityParams(activity, requestCode);
params.intent = intent;
params.options = options;
activity.startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
return true;
}
/**
* Removes any active ProxyActivityStarter task and sends RESULT_CANCELED to Launcher.
*
* ProxyActivityStarter is started with clear task to reset the task after which it removes the
* task itself.
*/
public static void resetPendingActivityResults(Launcher launcher, int requestCode) {
launcher.onActivityResult(requestCode, RESULT_CANCELED, null);
launcher.startActivity(ProxyActivityStarter.getLaunchIntent(launcher, null));
}
public static ScaleAndTranslation getOverviewScaleAndTranslationForNormalState(Launcher l) {
if (SysUINavigationMode.getMode(l) == Mode.NO_BUTTON) {
float offscreenTranslationX = l.getDeviceProfile().widthPx