• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.app.ActivityClient;
24 import android.app.ActivityOptions;
25 import android.app.ActivityThread.ActivityClientRecord;
26 import android.app.ClientTransactionHandler;
27 import android.app.IActivityClientController;
28 import android.app.ProfilerInfo;
29 import android.app.ResultInfo;
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.content.Intent;
32 import android.content.pm.ActivityInfo;
33 import android.content.res.CompatibilityInfo;
34 import android.content.res.Configuration;
35 import android.os.BaseBundle;
36 import android.os.Bundle;
37 import android.os.IBinder;
38 import android.os.Parcel;
39 import android.os.PersistableBundle;
40 import android.os.Trace;
41 
42 import com.android.internal.app.IVoiceInteractor;
43 import com.android.internal.content.ReferrerIntent;
44 
45 import java.util.List;
46 import java.util.Objects;
47 
48 /**
49  * Request to launch an activity.
50  * @hide
51  */
52 public class LaunchActivityItem extends ClientTransactionItem {
53 
54     @UnsupportedAppUsage
55     private Intent mIntent;
56     private int mIdent;
57     @UnsupportedAppUsage
58     private ActivityInfo mInfo;
59     private Configuration mCurConfig;
60     private Configuration mOverrideConfig;
61     private CompatibilityInfo mCompatInfo;
62     private String mReferrer;
63     private IVoiceInteractor mVoiceInteractor;
64     private int mProcState;
65     private Bundle mState;
66     private PersistableBundle mPersistentState;
67     private List<ResultInfo> mPendingResults;
68     private List<ReferrerIntent> mPendingNewIntents;
69     private ActivityOptions mActivityOptions;
70     private boolean mIsForward;
71     private ProfilerInfo mProfilerInfo;
72     private IBinder mAssistToken;
73     private IBinder mShareableActivityToken;
74     private boolean mLaunchedFromBubble;
75     private IBinder mTaskFragmentToken;
76     /**
77      * It is only non-null if the process is the first time to launch activity. It is only an
78      * optimization for quick look up of the interface so the field is ignored for comparison.
79      */
80     private IActivityClientController mActivityClientController;
81 
82     @Override
preExecute(ClientTransactionHandler client, IBinder token)83     public void preExecute(ClientTransactionHandler client, IBinder token) {
84         client.countLaunchingActivities(1);
85         client.updateProcessState(mProcState, false);
86         client.updatePendingConfiguration(mCurConfig);
87         if (mActivityClientController != null) {
88             ActivityClient.setActivityClientController(mActivityClientController);
89         }
90     }
91 
92     @Override
execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)93     public void execute(ClientTransactionHandler client, IBinder token,
94             PendingTransactionActions pendingActions) {
95         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
96         ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
97                 mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
98                 mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
99                 client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
100                 mTaskFragmentToken);
101         client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
102         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
103     }
104 
105     @Override
postExecute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)106     public void postExecute(ClientTransactionHandler client, IBinder token,
107             PendingTransactionActions pendingActions) {
108         client.countLaunchingActivities(-1);
109     }
110 
111 
112     // ObjectPoolItem implementation
113 
LaunchActivityItem()114     private LaunchActivityItem() {}
115 
116     /** Obtain an instance initialized with provided params. */
obtain(Intent intent, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, IActivityClientController activityClientController, IBinder shareableActivityToken, boolean launchedFromBubble, IBinder taskFragmentToken)117     public static LaunchActivityItem obtain(Intent intent, int ident, ActivityInfo info,
118             Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo,
119             String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
120             PersistableBundle persistentState, List<ResultInfo> pendingResults,
121             List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
122             boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
123             IActivityClientController activityClientController, IBinder shareableActivityToken,
124             boolean launchedFromBubble, IBinder taskFragmentToken) {
125         LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
126         if (instance == null) {
127             instance = new LaunchActivityItem();
128         }
129         setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
130                 voiceInteractor, procState, state, persistentState, pendingResults,
131                 pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
132                 activityClientController, shareableActivityToken,
133                 launchedFromBubble, taskFragmentToken);
134 
135         return instance;
136     }
137 
138     @Override
recycle()139     public void recycle() {
140         setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
141                 null, false, null, null, null, null, false, null);
142         ObjectPool.recycle(this);
143     }
144 
145 
146     // Parcelable implementation
147 
148     /** Write from Parcel. */
149     @Override
writeToParcel(Parcel dest, int flags)150     public void writeToParcel(Parcel dest, int flags) {
151         dest.writeTypedObject(mIntent, flags);
152         dest.writeInt(mIdent);
153         dest.writeTypedObject(mInfo, flags);
154         dest.writeTypedObject(mCurConfig, flags);
155         dest.writeTypedObject(mOverrideConfig, flags);
156         dest.writeTypedObject(mCompatInfo, flags);
157         dest.writeString(mReferrer);
158         dest.writeStrongInterface(mVoiceInteractor);
159         dest.writeInt(mProcState);
160         dest.writeBundle(mState);
161         dest.writePersistableBundle(mPersistentState);
162         dest.writeTypedList(mPendingResults, flags);
163         dest.writeTypedList(mPendingNewIntents, flags);
164         dest.writeBundle(mActivityOptions != null ? mActivityOptions.toBundle() : null);
165         dest.writeBoolean(mIsForward);
166         dest.writeTypedObject(mProfilerInfo, flags);
167         dest.writeStrongBinder(mAssistToken);
168         dest.writeStrongInterface(mActivityClientController);
169         dest.writeStrongBinder(mShareableActivityToken);
170         dest.writeBoolean(mLaunchedFromBubble);
171         dest.writeStrongBinder(mTaskFragmentToken);
172     }
173 
174     /** Read from Parcel. */
LaunchActivityItem(Parcel in)175     private LaunchActivityItem(Parcel in) {
176         setValues(this, in.readTypedObject(Intent.CREATOR), in.readInt(),
177                 in.readTypedObject(ActivityInfo.CREATOR), in.readTypedObject(Configuration.CREATOR),
178                 in.readTypedObject(Configuration.CREATOR),
179                 in.readTypedObject(CompatibilityInfo.CREATOR), in.readString(),
180                 IVoiceInteractor.Stub.asInterface(in.readStrongBinder()), in.readInt(),
181                 in.readBundle(getClass().getClassLoader()),
182                 in.readPersistableBundle(getClass().getClassLoader()),
183                 in.createTypedArrayList(ResultInfo.CREATOR),
184                 in.createTypedArrayList(ReferrerIntent.CREATOR),
185                 ActivityOptions.fromBundle(in.readBundle()), in.readBoolean(),
186                 in.readTypedObject(ProfilerInfo.CREATOR),
187                 in.readStrongBinder(),
188                 IActivityClientController.Stub.asInterface(in.readStrongBinder()),
189                 in.readStrongBinder(),
190                 in.readBoolean(),
191                 in.readStrongBinder());
192     }
193 
194     public static final @NonNull Creator<LaunchActivityItem> CREATOR =
195             new Creator<LaunchActivityItem>() {
196         public LaunchActivityItem createFromParcel(Parcel in) {
197             return new LaunchActivityItem(in);
198         }
199 
200         public LaunchActivityItem[] newArray(int size) {
201             return new LaunchActivityItem[size];
202         }
203     };
204 
205     @Override
equals(@ullable Object o)206     public boolean equals(@Nullable Object o) {
207         if (this == o) {
208             return true;
209         }
210         if (o == null || getClass() != o.getClass()) {
211             return false;
212         }
213         final LaunchActivityItem other = (LaunchActivityItem) o;
214         final boolean intentsEqual = (mIntent == null && other.mIntent == null)
215                 || (mIntent != null && mIntent.filterEquals(other.mIntent));
216         return intentsEqual && mIdent == other.mIdent
217                 && activityInfoEqual(other.mInfo) && Objects.equals(mCurConfig, other.mCurConfig)
218                 && Objects.equals(mOverrideConfig, other.mOverrideConfig)
219                 && Objects.equals(mCompatInfo, other.mCompatInfo)
220                 && Objects.equals(mReferrer, other.mReferrer)
221                 && mProcState == other.mProcState && areBundlesEqualRoughly(mState, other.mState)
222                 && areBundlesEqualRoughly(mPersistentState, other.mPersistentState)
223                 && Objects.equals(mPendingResults, other.mPendingResults)
224                 && Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
225                 && (mActivityOptions == null) == (other.mActivityOptions == null)
226                 && mIsForward == other.mIsForward
227                 && Objects.equals(mProfilerInfo, other.mProfilerInfo)
228                 && Objects.equals(mAssistToken, other.mAssistToken)
229                 && Objects.equals(mShareableActivityToken, other.mShareableActivityToken)
230                 && Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken);
231     }
232 
233     @Override
hashCode()234     public int hashCode() {
235         int result = 17;
236         result = 31 * result + mIntent.filterHashCode();
237         result = 31 * result + mIdent;
238         result = 31 * result + Objects.hashCode(mCurConfig);
239         result = 31 * result + Objects.hashCode(mOverrideConfig);
240         result = 31 * result + Objects.hashCode(mCompatInfo);
241         result = 31 * result + Objects.hashCode(mReferrer);
242         result = 31 * result + Objects.hashCode(mProcState);
243         result = 31 * result + getRoughBundleHashCode(mState);
244         result = 31 * result + getRoughBundleHashCode(mPersistentState);
245         result = 31 * result + Objects.hashCode(mPendingResults);
246         result = 31 * result + Objects.hashCode(mPendingNewIntents);
247         result = 31 * result + (mActivityOptions != null ? 1 : 0);
248         result = 31 * result + (mIsForward ? 1 : 0);
249         result = 31 * result + Objects.hashCode(mProfilerInfo);
250         result = 31 * result + Objects.hashCode(mAssistToken);
251         result = 31 * result + Objects.hashCode(mShareableActivityToken);
252         result = 31 * result + Objects.hashCode(mTaskFragmentToken);
253         return result;
254     }
255 
activityInfoEqual(ActivityInfo other)256     private boolean activityInfoEqual(ActivityInfo other) {
257         if (mInfo == null) {
258             return other == null;
259         }
260         return other != null && mInfo.flags == other.flags
261                 && mInfo.getMaxAspectRatio() == other.getMaxAspectRatio()
262                 && Objects.equals(mInfo.launchToken, other.launchToken)
263                 && Objects.equals(mInfo.getComponentName(), other.getComponentName());
264     }
265 
266     /**
267      * This method may be used to compare a parceled item with another unparceled item, and the
268      * parceled bundle may contain customized class that will raise BadParcelableException when
269      * unparceling if a customized class loader is not set to the bundle. So the hash code is
270      * simply determined by the bundle is empty or not.
271      */
getRoughBundleHashCode(BaseBundle bundle)272     private static int getRoughBundleHashCode(BaseBundle bundle) {
273         return (bundle == null || bundle.isDefinitelyEmpty()) ? 0 : 1;
274     }
275 
276     /** Compares the bundles without unparceling them (avoid BadParcelableException). */
areBundlesEqualRoughly(BaseBundle a, BaseBundle b)277     private static boolean areBundlesEqualRoughly(BaseBundle a, BaseBundle b) {
278         return getRoughBundleHashCode(a) == getRoughBundleHashCode(b);
279     }
280 
281     @Override
toString()282     public String toString() {
283         return "LaunchActivityItem{intent=" + mIntent + ",ident=" + mIdent + ",info=" + mInfo
284                 + ",curConfig=" + mCurConfig + ",overrideConfig=" + mOverrideConfig
285                 + ",referrer=" + mReferrer + ",procState=" + mProcState + ",state=" + mState
286                 + ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
287                 + ",pendingNewIntents=" + mPendingNewIntents + ",options=" + mActivityOptions
288                 + ",profilerInfo=" + mProfilerInfo + ",assistToken=" + mAssistToken
289                 + ",shareableActivityToken=" + mShareableActivityToken + "}";
290     }
291 
292     // Using the same method to set and clear values to make sure we don't forget anything
setValues(LaunchActivityItem instance, Intent intent, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, IActivityClientController activityClientController, IBinder shareableActivityToken, boolean launchedFromBubble, IBinder taskFragmentToken)293     private static void setValues(LaunchActivityItem instance, Intent intent, int ident,
294             ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
295             CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
296             int procState, Bundle state, PersistableBundle persistentState,
297             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
298             ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
299             IBinder assistToken, IActivityClientController activityClientController,
300             IBinder shareableActivityToken, boolean launchedFromBubble, IBinder taskFragmentToken) {
301         instance.mIntent = intent;
302         instance.mIdent = ident;
303         instance.mInfo = info;
304         instance.mCurConfig = curConfig;
305         instance.mOverrideConfig = overrideConfig;
306         instance.mCompatInfo = compatInfo;
307         instance.mReferrer = referrer;
308         instance.mVoiceInteractor = voiceInteractor;
309         instance.mProcState = procState;
310         instance.mState = state;
311         instance.mPersistentState = persistentState;
312         instance.mPendingResults = pendingResults;
313         instance.mPendingNewIntents = pendingNewIntents;
314         instance.mActivityOptions = activityOptions;
315         instance.mIsForward = isForward;
316         instance.mProfilerInfo = profilerInfo;
317         instance.mAssistToken = assistToken;
318         instance.mActivityClientController = activityClientController;
319         instance.mShareableActivityToken = shareableActivityToken;
320         instance.mLaunchedFromBubble = launchedFromBubble;
321         instance.mTaskFragmentToken = taskFragmentToken;
322     }
323 }
324