1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.window.extensions.embedding; 18 19 import android.app.Activity; 20 import android.content.res.Configuration; 21 import android.util.Pair; 22 import android.util.Size; 23 import android.window.WindowContainerTransaction; 24 25 import androidx.annotation.NonNull; 26 27 /** 28 * Client-side descriptor of a split that holds two containers. 29 */ 30 class SplitContainer { 31 @NonNull 32 private final TaskFragmentContainer mPrimaryContainer; 33 @NonNull 34 private final TaskFragmentContainer mSecondaryContainer; 35 @NonNull 36 private final SplitRule mSplitRule; 37 @NonNull 38 private SplitAttributes mSplitAttributes; 39 SplitContainer(@onNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity, @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule, @NonNull SplitAttributes splitAttributes)40 SplitContainer(@NonNull TaskFragmentContainer primaryContainer, 41 @NonNull Activity primaryActivity, 42 @NonNull TaskFragmentContainer secondaryContainer, 43 @NonNull SplitRule splitRule, 44 @NonNull SplitAttributes splitAttributes) { 45 mPrimaryContainer = primaryContainer; 46 mSecondaryContainer = secondaryContainer; 47 mSplitRule = splitRule; 48 mSplitAttributes = splitAttributes; 49 50 if (shouldFinishPrimaryWithSecondary(splitRule)) { 51 if (mPrimaryContainer.getRunningActivityCount() == 1 52 && mPrimaryContainer.hasActivity(primaryActivity.getActivityToken())) { 53 mSecondaryContainer.addContainerToFinishOnExit(mPrimaryContainer); 54 } else { 55 // Only adding the activity to be finished vs. the entire TaskFragment while 56 // the secondary container exits because there are other unrelated activities in the 57 // primary TaskFragment. 58 mSecondaryContainer.addActivityToFinishOnExit(primaryActivity); 59 } 60 } 61 if (shouldFinishSecondaryWithPrimary(splitRule)) { 62 mPrimaryContainer.addContainerToFinishOnExit(mSecondaryContainer); 63 } 64 } 65 66 @NonNull getPrimaryContainer()67 TaskFragmentContainer getPrimaryContainer() { 68 return mPrimaryContainer; 69 } 70 71 @NonNull getSecondaryContainer()72 TaskFragmentContainer getSecondaryContainer() { 73 return mSecondaryContainer; 74 } 75 76 @NonNull getSplitRule()77 SplitRule getSplitRule() { 78 return mSplitRule; 79 } 80 81 @NonNull getSplitAttributes()82 SplitAttributes getSplitAttributes() { 83 return mSplitAttributes; 84 } 85 86 /** 87 * Updates the {@link SplitAttributes} to this container. 88 * It is usually used when there's a folding state change or 89 * {@link SplitController#onTaskFragmentParentInfoChanged(WindowContainerTransaction, int, 90 * Configuration)}. 91 */ setSplitAttributes(@onNull SplitAttributes splitAttributes)92 void setSplitAttributes(@NonNull SplitAttributes splitAttributes) { 93 mSplitAttributes = splitAttributes; 94 } 95 96 @NonNull getTaskContainer()97 TaskContainer getTaskContainer() { 98 return getPrimaryContainer().getTaskContainer(); 99 } 100 101 /** Returns the minimum dimension pair of primary container and secondary container. */ 102 @NonNull getMinDimensionsPair()103 Pair<Size, Size> getMinDimensionsPair() { 104 return new Pair<>(mPrimaryContainer.getMinDimensions(), 105 mSecondaryContainer.getMinDimensions()); 106 } 107 isPlaceholderContainer()108 boolean isPlaceholderContainer() { 109 return (mSplitRule instanceof SplitPlaceholderRule); 110 } 111 112 @NonNull toSplitInfo()113 SplitInfo toSplitInfo() { 114 return new SplitInfo(mPrimaryContainer.toActivityStack(), 115 mSecondaryContainer.toActivityStack(), mSplitAttributes); 116 } 117 shouldFinishPrimaryWithSecondary(@onNull SplitRule splitRule)118 static boolean shouldFinishPrimaryWithSecondary(@NonNull SplitRule splitRule) { 119 final boolean isPlaceholderContainer = splitRule instanceof SplitPlaceholderRule; 120 final boolean shouldFinishPrimaryWithSecondary = (splitRule instanceof SplitPairRule) 121 && ((SplitPairRule) splitRule).getFinishPrimaryWithSecondary() 122 != SplitRule.FINISH_NEVER; 123 return shouldFinishPrimaryWithSecondary || isPlaceholderContainer; 124 } 125 shouldFinishSecondaryWithPrimary(@onNull SplitRule splitRule)126 static boolean shouldFinishSecondaryWithPrimary(@NonNull SplitRule splitRule) { 127 final boolean isPlaceholderContainer = splitRule instanceof SplitPlaceholderRule; 128 final boolean shouldFinishSecondaryWithPrimary = (splitRule instanceof SplitPairRule) 129 && ((SplitPairRule) splitRule).getFinishSecondaryWithPrimary() 130 != SplitRule.FINISH_NEVER; 131 return shouldFinishSecondaryWithPrimary || isPlaceholderContainer; 132 } 133 shouldFinishAssociatedContainerWhenStacked(int finishBehavior)134 static boolean shouldFinishAssociatedContainerWhenStacked(int finishBehavior) { 135 return finishBehavior == SplitRule.FINISH_ALWAYS; 136 } 137 shouldFinishAssociatedContainerWhenAdjacent(int finishBehavior)138 static boolean shouldFinishAssociatedContainerWhenAdjacent(int finishBehavior) { 139 return finishBehavior == SplitRule.FINISH_ALWAYS 140 || finishBehavior == SplitRule.FINISH_ADJACENT; 141 } 142 getFinishPrimaryWithSecondaryBehavior(@onNull SplitRule splitRule)143 static int getFinishPrimaryWithSecondaryBehavior(@NonNull SplitRule splitRule) { 144 if (splitRule instanceof SplitPlaceholderRule) { 145 return ((SplitPlaceholderRule) splitRule).getFinishPrimaryWithSecondary(); 146 } 147 if (splitRule instanceof SplitPairRule) { 148 return ((SplitPairRule) splitRule).getFinishPrimaryWithSecondary(); 149 } 150 return SplitRule.FINISH_NEVER; 151 } 152 getFinishSecondaryWithPrimaryBehavior(@onNull SplitRule splitRule)153 static int getFinishSecondaryWithPrimaryBehavior(@NonNull SplitRule splitRule) { 154 if (splitRule instanceof SplitPlaceholderRule) { 155 return SplitRule.FINISH_ALWAYS; 156 } 157 if (splitRule instanceof SplitPairRule) { 158 return ((SplitPairRule) splitRule).getFinishSecondaryWithPrimary(); 159 } 160 return SplitRule.FINISH_NEVER; 161 } 162 isStickyPlaceholderRule(@onNull SplitRule splitRule)163 static boolean isStickyPlaceholderRule(@NonNull SplitRule splitRule) { 164 if (!(splitRule instanceof SplitPlaceholderRule)) { 165 return false; 166 } 167 return ((SplitPlaceholderRule) splitRule).isSticky(); 168 } 169 170 @Override toString()171 public String toString() { 172 return "SplitContainer{" 173 + " primaryContainer=" + mPrimaryContainer 174 + " secondaryContainer=" + mSecondaryContainer 175 + " splitRule=" + mSplitRule 176 + " splitAttributes" + mSplitAttributes 177 + "}"; 178 } 179 } 180