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

Commit 0bda5605 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Introduce Parcelable data class to encapsulate the parcelable data" into main

parents dd998443 f88a7bcc
Loading
Loading
Loading
Loading
+14 −6
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.Log;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;


import java.util.ArrayList;
import java.util.List;
import java.util.List;


/**
/**
@@ -80,9 +81,14 @@ class BackupHelper {
        }
        }


        if (DEBUG) Log.d(TAG, "Start to back up " + taskContainers);
        if (DEBUG) Log.d(TAG, "Start to back up " + taskContainers);
        final List<ParcelableTaskContainerData> parcelableTaskContainerDataList = new ArrayList<>(
                taskContainers.size());
        for (TaskContainer taskContainer : taskContainers) {
            parcelableTaskContainerDataList.add(taskContainer.getParcelableData());
        }
        final Bundle state = new Bundle();
        final Bundle state = new Bundle();
        state.setClassLoader(TaskContainer.class.getClassLoader());
        state.setClassLoader(ParcelableTaskContainerData.class.getClassLoader());
        state.putParcelableList(KEY_TASK_CONTAINERS, taskContainers);
        state.putParcelableList(KEY_TASK_CONTAINERS, parcelableTaskContainerDataList);
        mController.setSavedState(state);
        mController.setSavedState(state);
    }
    }


@@ -91,10 +97,12 @@ class BackupHelper {
            return;
            return;
        }
        }


        final List<TaskContainer> taskContainers = savedState.getParcelableArrayList(
        final List<ParcelableTaskContainerData> parcelableTaskContainerDataList =
                KEY_TASK_CONTAINERS, TaskContainer.class);
                savedState.getParcelableArrayList(KEY_TASK_CONTAINERS,
        for (TaskContainer taskContainer : taskContainers) {
                        ParcelableTaskContainerData.class);
            if (DEBUG) Log.d(TAG, "restore task " + taskContainer.getTaskId());
        for (ParcelableTaskContainerData data : parcelableTaskContainerDataList) {
            final TaskContainer taskContainer = new TaskContainer(data, mController);
            if (DEBUG) Log.d(TAG, "Restoring task " + taskContainer.getTaskId());
            // TODO(b/289875940): implement the TaskContainer restoration.
            // TODO(b/289875940): implement the TaskContainer restoration.
        }
        }
    }
    }
+116 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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 androidx.window.extensions.embedding;

import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * This class holds the Parcelable data of a {@link SplitContainer}.
 */
class ParcelableSplitContainerData implements Parcelable {

    /**
     * A reference to the target {@link SplitContainer} that owns the data. This will not be
     * parcelled and will be {@code null} when the data is created from a parcel.
     */
    @Nullable
    final SplitContainer mSplitContainer;

    @NonNull
    final IBinder mToken;

    @NonNull
    private final IBinder mPrimaryContainerToken;

    @NonNull
    private final IBinder mSecondaryContainerToken;

    // TODO(b/289875940): making this as non-null once the tag can be auto-generated from the rule.
    @Nullable
    final String mSplitRuleTag;

    /**
     * Whether the selection of which container is primary can be changed at runtime. Runtime
     * updates is currently possible only for {@link SplitPinContainer}
     *
     * @see SplitPinContainer
     */
    final boolean mIsPrimaryContainerMutable;

    ParcelableSplitContainerData(@NonNull SplitContainer splitContainer, @NonNull IBinder token,
            @NonNull IBinder primaryContainerToken, @NonNull IBinder secondaryContainerToken,
            @Nullable String splitRuleTag, boolean isPrimaryContainerMutable) {
        mSplitContainer = splitContainer;
        mToken = token;
        mPrimaryContainerToken = primaryContainerToken;
        mSecondaryContainerToken = secondaryContainerToken;
        mSplitRuleTag = splitRuleTag;
        mIsPrimaryContainerMutable = isPrimaryContainerMutable;
    }

    private ParcelableSplitContainerData(Parcel in) {
        mSplitContainer = null;
        mToken = in.readStrongBinder();
        mPrimaryContainerToken = in.readStrongBinder();
        mSecondaryContainerToken = in.readStrongBinder();
        mSplitRuleTag = in.readString();
        mIsPrimaryContainerMutable = in.readBoolean();
    }

    public static final Creator<ParcelableSplitContainerData> CREATOR = new Creator<>() {
        @Override
        public ParcelableSplitContainerData createFromParcel(Parcel in) {
            return new ParcelableSplitContainerData(in);
        }

        @Override
        public ParcelableSplitContainerData[] newArray(int size) {
            return new ParcelableSplitContainerData[size];
        }
    };

    @NonNull
    private IBinder getPrimaryContainerToken() {
        return mSplitContainer != null ? mSplitContainer.getPrimaryContainer().getToken()
                : mPrimaryContainerToken;
    }

    @NonNull
    private IBinder getSecondaryContainerToken() {
        return mSplitContainer != null ? mSplitContainer.getSecondaryContainer().getToken()
                : mSecondaryContainerToken;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStrongBinder(mToken);
        dest.writeStrongBinder(getPrimaryContainerToken());
        dest.writeStrongBinder(getSecondaryContainerToken());
        dest.writeString(mSplitRuleTag);
        dest.writeBoolean(mIsPrimaryContainerMutable);
    }
}
+127 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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 androidx.window.extensions.embedding;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * This class holds the Parcelable data of a {@link TaskContainer}.
 */
class ParcelableTaskContainerData implements Parcelable {

    /**
     * A reference to the target {@link TaskContainer} that owns the data. This will not be
     * parcelled and will be {@code null} when the data is created from a parcel.
     */
    @Nullable
    final TaskContainer mTaskContainer;

    /**
     * The unique task id.
     */
    final int mTaskId;

    /**
     * The parcelable data of the active TaskFragmentContainers in this Task.
     * Note that this will only be populated before parcelling, and will not be copied when
     * making a new instance copy.
     */
    @NonNull
    private final List<ParcelableTaskFragmentContainerData>
            mParcelableTaskFragmentContainerDataList = new ArrayList<>();

    /**
     * The parcelable data of the SplitContainers in this Task.
     * Note that this will only be populated before parcelling, and will not be copied when
     * making a new instance copy.
     */
    @NonNull
    private final List<ParcelableSplitContainerData> mParcelableSplitContainerDataList =
            new ArrayList<>();

    ParcelableTaskContainerData(int taskId, @NonNull TaskContainer taskContainer) {
        if (taskId == INVALID_TASK_ID) {
            throw new IllegalArgumentException("Invalid Task id");
        }

        mTaskId = taskId;
        mTaskContainer = taskContainer;
    }

    ParcelableTaskContainerData(@NonNull ParcelableTaskContainerData data,
            @NonNull TaskContainer taskContainer) {
        mTaskId = data.mTaskId;
        mTaskContainer = taskContainer;
    }

    private ParcelableTaskContainerData(Parcel in) {
        mTaskId = in.readInt();
        mTaskContainer = null;
        in.readParcelableList(mParcelableTaskFragmentContainerDataList,
                ParcelableTaskFragmentContainerData.class.getClassLoader(),
                ParcelableTaskFragmentContainerData.class);
        in.readParcelableList(mParcelableSplitContainerDataList,
                ParcelableSplitContainerData.class.getClassLoader(),
                ParcelableSplitContainerData.class);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mTaskId);
        dest.writeParcelableList(getParcelableTaskFragmentContainerDataList(), flags);
        dest.writeParcelableList(getParcelableSplitContainerDataList(), flags);
    }

    @NonNull
    List<? extends ParcelableTaskFragmentContainerData>
            getParcelableTaskFragmentContainerDataList() {
        return mTaskContainer != null ? mTaskContainer.getParcelableTaskFragmentContainerDataList()
                : mParcelableTaskFragmentContainerDataList;
    }

    @NonNull
    List<? extends ParcelableSplitContainerData> getParcelableSplitContainerDataList() {
        return mTaskContainer != null ? mTaskContainer.getParcelableSplitContainerDataList()
                : mParcelableSplitContainerDataList;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<ParcelableTaskContainerData> CREATOR = new Creator<>() {
        @Override
        public ParcelableTaskContainerData createFromParcel(Parcel in) {
            return new ParcelableTaskContainerData(in);
        }

        @Override
        public ParcelableTaskContainerData[] newArray(int size) {
            return new ParcelableTaskContainerData[size];
        }
    };
}
+105 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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 androidx.window.extensions.embedding;

import android.app.Activity;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * This class holds the Parcelable data of a {@link TaskFragmentContainer}.
 */
class ParcelableTaskFragmentContainerData implements Parcelable {

    /**
     * Client-created token that uniquely identifies the task fragment container instance.
     */
    @NonNull
    final IBinder mToken;

    /**
     * The tag specified in launch options. {@code null} if this taskFragment container is not an
     * overlay container.
     */
    @Nullable
    final String mOverlayTag;

    /**
     * The associated {@link Activity#getActivityToken()} of the overlay container.
     * Must be {@code null} for non-overlay container.
     * <p>
     * If an overlay container is associated with an activity, this overlay container will be
     * dismissed when the associated activity is destroyed. If the overlay container is visible,
     * activity will be launched on top of the overlay container and expanded to fill the parent
     * container.
     */
    @Nullable
    final IBinder mAssociatedActivityToken;

    /**
     * Bounds that were requested last via {@link android.window.WindowContainerTransaction}.
     */
    @NonNull
    final Rect mLastRequestedBounds;

    ParcelableTaskFragmentContainerData(@NonNull IBinder token, @Nullable String overlayTag,
            @Nullable IBinder associatedActivityToken) {
        mToken = token;
        mOverlayTag = overlayTag;
        mAssociatedActivityToken = associatedActivityToken;
        mLastRequestedBounds = new Rect();
    }

    private ParcelableTaskFragmentContainerData(Parcel in) {
        mToken = in.readStrongBinder();
        mOverlayTag = in.readString();
        mAssociatedActivityToken = in.readStrongBinder();
        mLastRequestedBounds = in.readTypedObject(Rect.CREATOR);
    }

    public static final Creator<ParcelableTaskFragmentContainerData> CREATOR = new Creator<>() {
        @Override
        public ParcelableTaskFragmentContainerData createFromParcel(Parcel in) {
            return new ParcelableTaskFragmentContainerData(in);
        }

        @Override
        public ParcelableTaskFragmentContainerData[] newArray(int size) {
            return new ParcelableTaskFragmentContainerData[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStrongBinder(mToken);
        dest.writeString(mOverlayTag);
        dest.writeStrongBinder(mAssociatedActivityToken);
        dest.writeTypedObject(mLastRequestedBounds, flags);
    }

}
+13 −15
Original line number Original line Diff line number Diff line
@@ -32,6 +32,8 @@ import androidx.window.extensions.core.util.function.Function;
 * Client-side descriptor of a split that holds two containers.
 * Client-side descriptor of a split that holds two containers.
 */
 */
class SplitContainer {
class SplitContainer {
    @NonNull
    private final ParcelableSplitContainerData mParcelableData;
    @NonNull
    @NonNull
    private TaskFragmentContainer mPrimaryContainer;
    private TaskFragmentContainer mPrimaryContainer;
    @NonNull
    @NonNull
@@ -44,16 +46,6 @@ class SplitContainer {
    /** @see SplitContainer#getDefaultSplitAttributes() */
    /** @see SplitContainer#getDefaultSplitAttributes() */
    @NonNull
    @NonNull
    private SplitAttributes mDefaultSplitAttributes;
    private SplitAttributes mDefaultSplitAttributes;
    @NonNull
    private final IBinder mToken;

    /**
     * Whether the selection of which container is primary can be changed at runtime. Runtime
     * updates is currently possible only for {@link SplitPinContainer}
     *
     * @see SplitPinContainer
     */
    private final boolean mIsPrimaryContainerMutable;


    SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
    SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
            @NonNull Activity primaryActivity,
            @NonNull Activity primaryActivity,
@@ -69,13 +61,14 @@ class SplitContainer {
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull SplitRule splitRule,
            @NonNull SplitRule splitRule,
            @NonNull SplitAttributes splitAttributes, boolean isPrimaryContainerMutable) {
            @NonNull SplitAttributes splitAttributes, boolean isPrimaryContainerMutable) {
        mParcelableData = new ParcelableSplitContainerData(this, new Binder("SplitContainer"),
                primaryContainer.getToken(), secondaryContainer.getToken(), splitRule.getTag(),
                isPrimaryContainerMutable);
        mPrimaryContainer = primaryContainer;
        mPrimaryContainer = primaryContainer;
        mSecondaryContainer = secondaryContainer;
        mSecondaryContainer = secondaryContainer;
        mSplitRule = splitRule;
        mSplitRule = splitRule;
        mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
        mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
        mCurrentSplitAttributes = splitAttributes;
        mCurrentSplitAttributes = splitAttributes;
        mToken = new Binder("SplitContainer");
        mIsPrimaryContainerMutable = isPrimaryContainerMutable;


        if (shouldFinishPrimaryWithSecondary(splitRule)) {
        if (shouldFinishPrimaryWithSecondary(splitRule)) {
            if (mPrimaryContainer.getRunningActivityCount() == 1
            if (mPrimaryContainer.getRunningActivityCount() == 1
@@ -94,7 +87,7 @@ class SplitContainer {
    }
    }


    void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
    void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
        if (!mIsPrimaryContainerMutable) {
        if (!mParcelableData.mIsPrimaryContainerMutable) {
            throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
            throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
        }
        }
        mPrimaryContainer = primaryContainer;
        mPrimaryContainer = primaryContainer;
@@ -150,7 +143,12 @@ class SplitContainer {


    @NonNull
    @NonNull
    IBinder getToken() {
    IBinder getToken() {
        return mToken;
        return mParcelableData.mToken;
    }

    @NonNull
    ParcelableSplitContainerData getParcelableData() {
        return mParcelableData;
    }
    }


    /**
    /**
@@ -201,7 +199,7 @@ class SplitContainer {
            return null;
            return null;
        }
        }
        return new SplitInfo(primaryActivityStack, secondaryActivityStack,
        return new SplitInfo(primaryActivityStack, secondaryActivityStack,
                mCurrentSplitAttributes, SplitInfo.Token.createFromBinder(mToken));
                mCurrentSplitAttributes, SplitInfo.Token.createFromBinder(mParcelableData.mToken));
    }
    }


    static boolean shouldFinishPrimaryWithSecondary(@NonNull SplitRule splitRule) {
    static boolean shouldFinishPrimaryWithSecondary(@NonNull SplitRule splitRule) {
Loading