Merge ""Springboard" from system to new chooser."

This commit is contained in:
Joshua Trask
2021-11-18 22:41:14 +00:00
committed by Android (Google) Code Review
2 changed files with 177 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.SharedElementCallback;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
@@ -70,9 +71,11 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
@@ -151,6 +154,19 @@ public class ChooserActivity extends ResolverActivity implements
ChooserListAdapter.ChooserListCommunicator,
SelectableTargetInfoCommunicator {
private static final String TAG = "ChooserActivity";
/**
* Whether this chooser is operating in "headless springboard" mode (as determined during
* onCreate). In this mode, our activity sits in the background and waits for the new
* "unbundled" chooser to handle the Sharesheet experience; the system ChooserActivity is
* responsible only for providing the startActivityAsCaller permission token and keeping it
* valid for the life of the unbundled delegate activity.
*
* TODO: when the unbundled chooser is fully launched, the system-side "springboard" can use a
* simpler implementation that doesn't inherit from ResolverActivity.
*/
private boolean mIsHeadlessSpringboardActivity;
private AppPredictor mPersonalAppPredictor;
private AppPredictor mWorkAppPredictor;
private boolean mShouldDisplayLandscape;
@@ -235,6 +251,11 @@ public class ChooserActivity extends ResolverActivity implements
private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f;
private boolean mEnableChooserDelegate =
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER,
false);
private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7;
private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS,
@@ -500,6 +521,12 @@ public class ChooserActivity extends ResolverActivity implements
@Override
protected void onCreate(Bundle savedInstanceState) {
if (handOverToDelegateChooser()) {
super_onCreate(savedInstanceState);
mIsHeadlessSpringboardActivity = true;
return;
}
final long intentReceivedTime = System.currentTimeMillis();
getChooserActivityLogger().logSharesheetTriggered();
// This is the only place this value is being set. Effectively final.
@@ -714,6 +741,64 @@ public class ChooserActivity extends ResolverActivity implements
postponeEnterTransition();
}
private boolean handOverToDelegateChooser() {
// Check the explicit classname so that we don't interfere with the flow of any subclasses.
if (!this.getClass().getName().equals("com.android.internal.app.ChooserActivity")
|| !mEnableChooserDelegate) {
return false;
}
try {
IBinder permissionToken = ActivityTaskManager.getService()
.requestStartActivityPermissionToken(getActivityToken());
Intent delegationIntent = new Intent();
final ComponentName delegateActivity = ComponentName.unflattenFromString(
Resources.getSystem().getString(R.string.config_chooserActivity));
delegationIntent.setComponent(delegateActivity);
delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent());
delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
delegationIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
// Don't close until the delegate finishes, or the token will be invalidated.
mAwaitingDelegateResponse = true;
startActivityForResult(delegationIntent, REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER);
return true;
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
return false;
}
@Override
protected void onRestart() {
if (mIsHeadlessSpringboardActivity) {
super_onRestart();
return;
}
super.onRestart();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if (mIsHeadlessSpringboardActivity) {
super_onSaveInstanceState(outState);
return;
}
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mIsHeadlessSpringboardActivity) {
super_onRestoreInstanceState(savedInstanceState);
return;
}
super.onRestoreInstanceState(savedInstanceState);
}
@Override
protected int appliedThemeResId() {
return R.style.Theme_DeviceDefault_Chooser;
@@ -998,6 +1083,11 @@ public class ChooserActivity extends ResolverActivity implements
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mIsHeadlessSpringboardActivity) {
super_onConfigurationChanged(newConfig);
return;
}
super.onConfigurationChanged(newConfig);
ViewPager viewPager = findViewById(R.id.profile_pager);
if (viewPager.isLayoutRtl()) {
@@ -1543,6 +1633,11 @@ public class ChooserActivity extends ResolverActivity implements
@Override
protected void onDestroy() {
super.onDestroy();
if (mIsHeadlessSpringboardActivity) {
return;
}
if (mRefinementResultReceiver != null) {
mRefinementResultReceiver.destroy();
mRefinementResultReceiver = null;

View File

@@ -152,7 +152,7 @@ public class ResolverActivity extends Activity implements
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
private static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20;
protected static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20;
private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
@@ -323,6 +323,86 @@ public class ResolverActivity extends Activity implements
super.onCreate(savedInstanceState);
}
/**
* Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
* where we hand over to the unbundled chooser (while violating many of the invariants of a
* typical ResolverActivity implementation). Subclasses running in this mode need to be able
* to opt-out of the normal ResolverActivity behavior.
*
* TODO: this should be removed later on in the unbundling migration, when the springboard
* activity no longer needs to derive from ResolverActivity. The hold-over design here is
* <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
* requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
* implementations that depend on the invariants that are violated in the headless mode). If
* necessary, we could instead consider using a springboard-only activity on the system side
* immediately, which would delegate either to the unbundled chooser, or to a
* (properly-inheriting) system ChooserActivity. This would have performance implications even
* when the unbundling experiment is disabled.
*/
protected void super_onRestart() {
super.onRestart();
}
/**
* Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
* where we hand over to the unbundled chooser (while violating many of the invariants of a
* typical ResolverActivity implementation). Subclasses running in this mode need to be able
* to opt-out of the normal ResolverActivity behavior.
*
* TODO: this should be removed later on in the unbundling migration, when the springboard
* activity no longer needs to derive from ResolverActivity. The hold-over design here is
* <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
* requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
* implementations that depend on the invariants that are violated in the headless mode). If
* necessary, we could instead consider using a springboard-only activity on the system side
* immediately, which would delegate either to the unbundled chooser, or to a
* (properly-inheriting) system ChooserActivity. This would have performance implications even
* when the unbundling experiment is disabled.
*/
protected void super_onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
/**
* Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
* where we hand over to the unbundled chooser (while violating many of the invariants of a
* typical ResolverActivity implementation). Subclasses running in this mode need to be able
* to opt-out of the normal ResolverActivity behavior.
*
* TODO: this should be removed later on in the unbundling migration, when the springboard
* activity no longer needs to derive from ResolverActivity. The hold-over design here is
* <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
* requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
* implementations that depend on the invariants that are violated in the headless mode). If
* necessary, we could instead consider using a springboard-only activity on the system side
* immediately, which would delegate either to the unbundled chooser, or to a
* (properly-inheriting) system ChooserActivity. This would have performance implications even
* when the unbundling experiment is disabled.
*/
protected void super_onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
/**
* Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
* where we hand over to the unbundled chooser (while violating many of the invariants of a
* typical ResolverActivity implementation). Subclasses running in this mode need to be able
* to opt-out of the normal ResolverActivity behavior.
*
* TODO: this should be removed later on in the unbundling migration, when the springboard
* activity no longer needs to derive from ResolverActivity. The hold-over design here is
* <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
* requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
* implementations that depend on the invariants that are violated in the headless mode). If
* necessary, we could instead consider using a springboard-only activity on the system side
* immediately, which would delegate either to the unbundled chooser, or to a
* (properly-inheriting) system ChooserActivity. This would have performance implications even
* when the unbundling experiment is disabled.
*/
public void super_onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// Use a specialized prompt when we're handling the 'Home' app startActivity()
@@ -877,7 +957,7 @@ public class ResolverActivity extends Activity implements
}
final Intent intent = getIntent();
if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
&& !mResolvingHome && !mRetainInOnStop) {
&& !mResolvingHome && !mRetainInOnStop && !mAwaitingDelegateResponse) {
// This resolver is in the unusual situation where it has been
// launched at the top of a new task. We don't let it be added
// to the recent tasks shown to the user, and we need to make sure