Loading core/java/com/android/internal/app/ChooserActivity.java +95 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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; Loading core/java/com/android/internal/app/ResolverActivity.java +82 −2 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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() Loading Loading @@ -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 Loading Loading
core/java/com/android/internal/app/ChooserActivity.java +95 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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()) { Loading Loading @@ -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; Loading
core/java/com/android/internal/app/ResolverActivity.java +82 −2 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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() Loading Loading @@ -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 Loading