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