1 /* 2 * Copyright 2017 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 android.app.servertransaction; 18 19 import static android.app.ActivityThread.DEBUG_ORDER; 20 21 import static java.util.Objects.requireNonNull; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.app.ActivityThread.ActivityClientRecord; 26 import android.app.ClientTransactionHandler; 27 import android.app.ResultInfo; 28 import android.content.res.CompatibilityInfo; 29 import android.os.IBinder; 30 import android.os.Parcel; 31 import android.os.Trace; 32 import android.util.MergedConfiguration; 33 import android.util.Slog; 34 import android.window.ActivityWindowInfo; 35 36 import com.android.internal.content.ReferrerIntent; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.Objects; 41 42 /** 43 * Activity relaunch callback. 44 * 45 * @hide 46 */ 47 public class ActivityRelaunchItem extends ActivityTransactionItem { 48 49 private static final String TAG = "ActivityRelaunchItem"; 50 51 @Nullable 52 private final List<ResultInfo> mPendingResults; 53 54 @Nullable 55 private final List<ReferrerIntent> mPendingNewIntents; 56 57 @NonNull 58 private final MergedConfiguration mConfig; 59 60 @NonNull 61 private final ActivityWindowInfo mActivityWindowInfo; 62 63 private final int mConfigChanges; 64 private final boolean mPreserveWindow; 65 66 /** 67 * A record that was properly configured for relaunch. Execution will be cancelled if not 68 * initialized after {@link #preExecute(ClientTransactionHandler)}. 69 */ 70 @Nullable 71 private ActivityClientRecord mActivityClientRecord; 72 ActivityRelaunchItem(@onNull IBinder activityToken, @Nullable List<ResultInfo> pendingResults, @Nullable List<ReferrerIntent> pendingNewIntents, int configChanges, @NonNull MergedConfiguration config, boolean preserveWindow, @NonNull ActivityWindowInfo activityWindowInfo)73 public ActivityRelaunchItem(@NonNull IBinder activityToken, 74 @Nullable List<ResultInfo> pendingResults, 75 @Nullable List<ReferrerIntent> pendingNewIntents, int configChanges, 76 @NonNull MergedConfiguration config, boolean preserveWindow, 77 @NonNull ActivityWindowInfo activityWindowInfo) { 78 super(activityToken); 79 mPendingResults = pendingResults != null ? new ArrayList<>(pendingResults) : null; 80 mPendingNewIntents = 81 pendingNewIntents != null ? new ArrayList<>(pendingNewIntents) : null; 82 mConfig = new MergedConfiguration(config); 83 mActivityWindowInfo = new ActivityWindowInfo(activityWindowInfo); 84 mConfigChanges = configChanges; 85 mPreserveWindow = preserveWindow; 86 } 87 88 @Override preExecute(@onNull ClientTransactionHandler client)89 public void preExecute(@NonNull ClientTransactionHandler client) { 90 // The local config is already scaled so only apply if this item is from server side. 91 if (!client.isExecutingLocalTransaction()) { 92 CompatibilityInfo.applyOverrideIfNeeded(mConfig); 93 } 94 mActivityClientRecord = client.prepareRelaunchActivity(getActivityToken(), mPendingResults, 95 mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow, mActivityWindowInfo); 96 } 97 98 @Override execute(@onNull ClientTransactionHandler client, @NonNull ActivityClientRecord r, @NonNull PendingTransactionActions pendingActions)99 public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r, 100 @NonNull PendingTransactionActions pendingActions) { 101 if (mActivityClientRecord == null) { 102 if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled"); 103 return; 104 } 105 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); 106 client.handleRelaunchActivity(mActivityClientRecord, pendingActions); 107 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 108 } 109 110 @Override postExecute(@onNull ClientTransactionHandler client, @NonNull PendingTransactionActions pendingActions)111 public void postExecute(@NonNull ClientTransactionHandler client, 112 @NonNull PendingTransactionActions pendingActions) { 113 final ActivityClientRecord r = getActivityClientRecord(client); 114 client.reportRelaunch(r); 115 } 116 117 // Parcelable implementation 118 119 /** Writes to Parcel. */ 120 @Override writeToParcel(@onNull Parcel dest, int flags)121 public void writeToParcel(@NonNull Parcel dest, int flags) { 122 super.writeToParcel(dest, flags); 123 dest.writeTypedList(mPendingResults, flags); 124 dest.writeTypedList(mPendingNewIntents, flags); 125 dest.writeTypedObject(mConfig, flags); 126 dest.writeTypedObject(mActivityWindowInfo, flags); 127 dest.writeInt(mConfigChanges); 128 dest.writeBoolean(mPreserveWindow); 129 } 130 131 /** Reads from Parcel. */ ActivityRelaunchItem(@onNull Parcel in)132 private ActivityRelaunchItem(@NonNull Parcel in) { 133 super(in); 134 mPendingResults = in.createTypedArrayList(ResultInfo.CREATOR); 135 mPendingNewIntents = in.createTypedArrayList(ReferrerIntent.CREATOR); 136 mConfig = requireNonNull(in.readTypedObject(MergedConfiguration.CREATOR)); 137 mActivityWindowInfo = requireNonNull(in.readTypedObject(ActivityWindowInfo.CREATOR)); 138 mConfigChanges = in.readInt(); 139 mPreserveWindow = in.readBoolean(); 140 } 141 142 public static final @NonNull Creator<ActivityRelaunchItem> CREATOR = 143 new Creator<>() { 144 public ActivityRelaunchItem createFromParcel(@NonNull Parcel in) { 145 return new ActivityRelaunchItem(in); 146 } 147 148 public ActivityRelaunchItem[] newArray(int size) { 149 return new ActivityRelaunchItem[size]; 150 } 151 }; 152 153 @Override equals(@ullable Object o)154 public boolean equals(@Nullable Object o) { 155 if (this == o) { 156 return true; 157 } 158 if (!super.equals(o)) { 159 return false; 160 } 161 final ActivityRelaunchItem other = (ActivityRelaunchItem) o; 162 return Objects.equals(mPendingResults, other.mPendingResults) 163 && Objects.equals(mPendingNewIntents, other.mPendingNewIntents) 164 && Objects.equals(mConfig, other.mConfig) 165 && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo) 166 && mConfigChanges == other.mConfigChanges 167 && mPreserveWindow == other.mPreserveWindow; 168 } 169 170 @Override hashCode()171 public int hashCode() { 172 int result = 17; 173 result = 31 * result + super.hashCode(); 174 result = 31 * result + Objects.hashCode(mPendingResults); 175 result = 31 * result + Objects.hashCode(mPendingNewIntents); 176 result = 31 * result + Objects.hashCode(mConfig); 177 result = 31 * result + Objects.hashCode(mActivityWindowInfo); 178 result = 31 * result + mConfigChanges; 179 result = 31 * result + (mPreserveWindow ? 1 : 0); 180 return result; 181 } 182 183 @Override toString()184 public String toString() { 185 return "ActivityRelaunchItem{" + super.toString() 186 + ",pendingResults=" + mPendingResults 187 + ",pendingNewIntents=" + mPendingNewIntents 188 + ",config=" + mConfig 189 + ",activityWindowInfo=" + mActivityWindowInfo 190 + ",configChanges=" + mConfigChanges 191 + ",preserveWindow=" + mPreserveWindow + "}"; 192 } 193 } 194