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

Commit a93ff445 authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "Add support for cross-activity scenes and transitions"

parents 3a621bbd cfbe9be5
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2830,6 +2830,8 @@ package android.app {
    method public java.lang.String getCallingPackage();
    method public int getChangingConfigurations();
    method public android.content.ComponentName getComponentName();
    method public android.transition.Scene getContentScene();
    method public android.transition.TransitionManager getContentTransitionManager();
    method public android.view.View getCurrentFocus();
    method public android.app.FragmentManager getFragmentManager();
    method public android.content.Intent getIntent();
@@ -2935,6 +2937,7 @@ package android.app {
    method public void reportFullyDrawn();
    method public final boolean requestWindowFeature(int);
    method public final void runOnUiThread(java.lang.Runnable);
    method public void setContentTransitionManager(android.transition.TransitionManager);
    method public void setContentView(int);
    method public void setContentView(android.view.View);
    method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
@@ -26363,10 +26366,15 @@ package android.transition {
    ctor public TransitionManager();
    method public static void beginDelayedTransition(android.view.ViewGroup);
    method public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
    method public android.transition.Transition getNamedTransition(java.lang.String, android.transition.Scene);
    method public android.transition.Transition getNamedTransition(android.transition.Scene, java.lang.String);
    method public java.lang.String[] getTargetSceneNames(android.transition.Scene);
    method public static void go(android.transition.Scene);
    method public static void go(android.transition.Scene, android.transition.Transition);
    method public void setTransition(android.transition.Scene, android.transition.Transition);
    method public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
    method public void setTransition(android.transition.Scene, java.lang.String, android.transition.Transition);
    method public void setTransition(java.lang.String, android.transition.Scene, android.transition.Transition);
    method public void transitionTo(android.transition.Scene);
  }
@@ -29289,6 +29297,7 @@ package android.view {
    method public final android.view.WindowManager.LayoutParams getAttributes();
    method public final android.view.Window.Callback getCallback();
    method public final android.view.Window getContainer();
    method public android.transition.Scene getContentScene();
    method public final android.content.Context getContext();
    method public abstract android.view.View getCurrentFocus();
    method public abstract android.view.View getDecorView();
@@ -29296,6 +29305,7 @@ package android.view {
    method protected final int getForcedWindowFlags();
    method public abstract android.view.LayoutInflater getLayoutInflater();
    method protected final int getLocalFeatures();
    method public android.transition.TransitionManager getTransitionManager();
    method public abstract int getVolumeControlStream();
    method public android.view.WindowManager getWindowManager();
    method public final android.content.res.TypedArray getWindowStyle();
@@ -29345,6 +29355,8 @@ package android.view {
    method public void setSoftInputMode(int);
    method public abstract void setTitle(java.lang.CharSequence);
    method public abstract deprecated void setTitleColor(int);
    method public void setTransitionManager(android.transition.TransitionManager);
    method public void setTransitionOptions(android.os.Bundle);
    method public void setType(int);
    method public void setUiOptions(int);
    method public void setUiOptions(int, int);
+72 −1
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package android.app;

import android.annotation.NonNull;
import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionManager;
import android.util.ArrayMap;
import android.util.SuperNotCalledException;
import com.android.internal.app.ActionBarImpl;
@@ -1989,6 +1992,41 @@ public class Activity extends ContextThemeWrapper
        initActionBar();
    }

    /**
     * Retrieve the {@link TransitionManager} responsible for default transitions in this window.
     * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
     *
     * <p>This method will return non-null after content has been initialized (e.g. by using
     * {@link #setContentView}) if {@link Window#FEATURE_CONTENT_TRANSITIONS} has been granted.</p>
     *
     * @return This window's content TransitionManager or null if none is set.
     */
    public TransitionManager getContentTransitionManager() {
        return getWindow().getTransitionManager();
    }

    /**
     * Set the {@link TransitionManager} to use for default transitions in this window.
     * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
     *
     * @param tm The TransitionManager to use for scene changes.
     */
    public void setContentTransitionManager(TransitionManager tm) {
        getWindow().setTransitionManager(tm);
    }

    /**
     * Retrieve the {@link Scene} representing this window's current content.
     * Requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
     *
     * <p>This method will return null if the current content is not represented by a Scene.</p>
     *
     * @return Current Scene being shown or null
     */
    public Scene getContentScene() {
        return getWindow().getContentScene();
    }

    /**
     * Sets whether this activity is finished when touched outside its window's
     * bounds.
@@ -3408,7 +3446,29 @@ public class Activity extends ContextThemeWrapper
     * @see #startActivity 
     */
    public void startActivityForResult(Intent intent, int requestCode) {
        final TransitionManager tm = getWindow().getTransitionManager();
        final Scene currScene = getWindow().getContentScene();
        final String[] targetSceneNames = currScene != null && tm != null ?
                tm.getTargetSceneNames(currScene) : null;

        if (targetSceneNames == null || targetSceneNames.length == 0) {
            startActivityForResult(intent, requestCode, null);
        } else {
            // TODO Capture the scene transition args and send along
            final ActivityOptions opts = ActivityOptions.makeSceneTransitionAnimation(
                    targetSceneNames, null,
                    new ActivityOptions.OnSceneTransitionStartedListener() {
                        @Override public void onSceneTransitionStarted(String destSceneName) {
                            final Transition t = tm.getNamedTransition(currScene, destSceneName);
                            // TODO Fill this in to notify the outgoing activity that it should
                            // treat this as a sync point for the transition - the target
                            // transition has started.
                            Log.d(TAG, "Scene transition to scene " + destSceneName +
                                    " transition " + t);
                        }
                    }, mHandler);
            startActivityForResult(intent, requestCode, opts.toBundle());
        }
    }

    /**
@@ -5229,6 +5289,16 @@ public class Activity extends ContextThemeWrapper
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config) {
        attach(context, aThread, instr, token, ident, application, intent, info, title, parent, id,
                lastNonConfigurationInstances, config, null);
    }

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, Bundle options) {
        attachBaseContext(context);

        mFragments.attachActivity(this, mContainer, null);
@@ -5265,6 +5335,7 @@ public class Activity extends ContextThemeWrapper
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mWindow.setTransitionOptions(options);
        mCurrentConfig = config;
    }

+48 −4
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

/**
@@ -30,6 +32,8 @@ import android.view.View;
 * Context.startActivity(Intent, Bundle)} and related methods.
 */
public class ActivityOptions {
    private static final String TAG = "ActivityOptions";

    /**
     * The package name that created the options.
     * @hide
@@ -481,8 +485,19 @@ public class ActivityOptions {
    }

    /** @hide */
    public IRemoteCallback getOnSceneTransitionStartedListener() {
        return mSceneTransitionStartedListener;
    public void dispatchSceneTransitionStarted(String destScene) {
        if (mSceneTransitionStartedListener != null) {
            Bundle data = null;
            if (!TextUtils.isEmpty(destScene)) {
                data = new Bundle();
                data.putString(KEY_DEST_SCENE_NAME_CHOSEN, destScene);
            }
            try {
                mSceneTransitionStartedListener.sendResult(data);
            } catch (RemoteException e) {
                Log.e(TAG, "Caught exception dispatching scene transition start", e);
            }
        }
    }

    /** @hide */
@@ -493,6 +508,12 @@ public class ActivityOptions {
            } catch (RemoteException e) {
            }
        }
        if (mSceneTransitionStartedListener != null) {
            try {
                mSceneTransitionStartedListener.sendResult(null);
            } catch (RemoteException e) {
            }
        }
    }

    /** @hide */
@@ -572,6 +593,8 @@ public class ActivityOptions {
                }
                mSceneTransitionStartedListener = otherOptions.mSceneTransitionStartedListener;
                mDestSceneNames = otherOptions.mDestSceneNames;
                mTransitionArgs = otherOptions.mTransitionArgs;
                mThumbnail = null;
                mAnimationStartedListener = null;
                break;
        }
@@ -595,7 +618,7 @@ public class ActivityOptions {
                b.putInt(KEY_ANIM_TYPE, mAnimationType);
                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
                b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                        != null ? mAnimationStartedListener.asBinder() : null);
                break;
            case ANIM_SCALE_UP:
@@ -611,10 +634,31 @@ public class ActivityOptions {
                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                b.putInt(KEY_ANIM_START_X, mStartX);
                b.putInt(KEY_ANIM_START_Y, mStartY);
                b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
                        != null ? mAnimationStartedListener.asBinder() : null);
                break;
            case ANIM_SCENE_TRANSITION:
                b.putInt(KEY_ANIM_TYPE, mAnimationType);
                b.putStringArray(KEY_DEST_SCENE_NAMES, mDestSceneNames);
                b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
                b.putBinder(KEY_SCENE_TRANSITION_START_LISTENER, mSceneTransitionStartedListener
                        != null ? mSceneTransitionStartedListener.asBinder() : null);
                break;
        }
        return b;
    }

    /**
     * Return the filtered options only meant to be seen by the target activity itself
     * @hide
     */
    public ActivityOptions forTargetActivity() {
        if (mAnimationType == ANIM_SCENE_TRANSITION) {
            final ActivityOptions result = new ActivityOptions();
            result.update(this);
            return result;
        }

        return null;
    }
}
+25 −12
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
@@ -68,12 +69,15 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.transition.Scene;
import android.transition.TransitionManager;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SuperNotCalledException;
@@ -284,6 +288,7 @@ public final class ActivityThread {
        boolean isForward;
        int pendingConfigChanges;
        boolean onlyLocalRequest;
        Bundle activityOptions;

        View mPendingRemoveWindow;
        WindowManager mPendingRemoveWindowManager;
@@ -576,9 +581,10 @@ public final class ActivityThread {
        }

        public final void scheduleResumeActivity(IBinder token, int processState,
                boolean isForward) {
                boolean isForward, Bundle resumeArgs) {
            updateProcessState(processState, false);
            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
            sendMessage(H.RESUME_ACTIVITY, new Pair<IBinder, Bundle>(token, resumeArgs),
                    isForward ? 1 : 0);
        }

        public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
@@ -594,7 +600,8 @@ public final class ActivityThread {
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                int procState, Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                Bundle resumeArgs) {

            updateProcessState(procState, false);

@@ -616,6 +623,7 @@ public final class ActivityThread {
            r.profileFile = profileName;
            r.profileFd = profileFd;
            r.autoStopProfiler = autoStopProfiler;
            r.activityOptions = resumeArgs;

            updatePendingConfiguration(curConfig);

@@ -1189,7 +1197,7 @@ public final class ActivityThread {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
@@ -1235,7 +1243,8 @@ public final class ActivityThread {
                    break;
                case RESUME_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
                    handleResumeActivity((IBinder)msg.obj, true,
                    final Pair<IBinder, Bundle> resumeArgs = (Pair<IBinder, Bundle>) msg.obj;
                    handleResumeActivity(resumeArgs.first, resumeArgs.second, true,
                            msg.arg1 != 0, true);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
@@ -2032,7 +2041,7 @@ public final class ActivityThread {
                    + ", comp=" + name
                    + ", token=" + token);
        }
        return performLaunchActivity(r, null);
        return performLaunchActivity(r, null, null);
    }

    public final Activity getActivity(IBinder token) {
@@ -2085,7 +2094,8 @@ public final class ActivityThread {
        sendMessage(H.CLEAN_UP_CONTEXT, cci);
    }

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent,
            Bundle options) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
@@ -2143,7 +2153,7 @@ public final class ActivityThread {
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);
                        r.embeddedID, r.lastNonConfigurationInstances, config, options);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
@@ -2242,12 +2252,13 @@ public final class ActivityThread {

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);
        Activity a = performLaunchActivity(r, customIntent);

        Activity a = performLaunchActivity(r, customIntent, r.activityOptions);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
            handleResumeActivity(r.token, r.activityOptions, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
@@ -2808,12 +2819,13 @@ public final class ActivityThread {
        r.mPendingRemoveWindowManager = null;
    }

    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
            boolean reallyResume) {
    final void handleResumeActivity(IBinder token, Bundle resumeArgs,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
@@ -3734,6 +3746,7 @@ public final class ActivityThread {
            }
        }
        r.startsNotResumed = tmp.startsNotResumed;
        r.activityOptions = null;

        handleLaunchActivity(r, currentIntent);
    }
+13 −6
Original line number Diff line number Diff line
@@ -113,7 +113,8 @@ public abstract class ApplicationThreadNative extends Binder
            IBinder b = data.readStrongBinder();
            int procState = data.readInt();
            boolean isForward = data.readInt() != 0;
            scheduleResumeActivity(b, procState, isForward);
            Bundle resumeArgs = data.readBundle();
            scheduleResumeActivity(b, procState, isForward, resumeArgs);
            return true;
        }
        
@@ -145,8 +146,10 @@ public abstract class ApplicationThreadNative extends Binder
            ParcelFileDescriptor profileFd = data.readInt() != 0
                    ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
            boolean autoStopProfiler = data.readInt() != 0;
            Bundle resumeArgs = data.readBundle();
            scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, procState, state,
                    ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler);
                    ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler,
                    resumeArgs);
            return true;
        }
        
@@ -696,13 +699,15 @@ class ApplicationThreadProxy implements IApplicationThread {
        data.recycle();
    }

    public final void scheduleResumeActivity(IBinder token, int procState, boolean isForward)
    public final void scheduleResumeActivity(IBinder token, int procState, boolean isForward,
            Bundle resumeArgs)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(procState);
        data.writeInt(isForward ? 1 : 0);
        data.writeBundle(resumeArgs);
        mRemote.transact(SCHEDULE_RESUME_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
@@ -723,7 +728,8 @@ class ApplicationThreadProxy implements IApplicationThread {
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            int procState, Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
    		String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
            Bundle resumeArgs)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -747,6 +753,7 @@ class ApplicationThreadProxy implements IApplicationThread {
            data.writeInt(0);
        }
        data.writeInt(autoStopProfiler ? 1 : 0);
        data.writeBundle(resumeArgs);
        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
Loading