Merge ""Springboard" from system to new chooser."
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user