• 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 static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
22 
23 import static java.util.Objects.requireNonNull;
24 
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.app.ActivityClient;
28 import android.app.ActivityManager.ProcessState;
29 import android.app.ActivityOptions.SceneTransitionInfo;
30 import android.app.ActivityThread.ActivityClientRecord;
31 import android.app.ClientTransactionHandler;
32 import android.app.IActivityClientController;
33 import android.app.ProfilerInfo;
34 import android.app.ResultInfo;
35 import android.compat.annotation.UnsupportedAppUsage;
36 import android.content.Intent;
37 import android.content.pm.ActivityInfo;
38 import android.content.res.CompatibilityInfo;
39 import android.content.res.Configuration;
40 import android.os.BaseBundle;
41 import android.os.Bundle;
42 import android.os.IBinder;
43 import android.os.Parcel;
44 import android.os.PersistableBundle;
45 import android.os.Trace;
46 import android.window.ActivityWindowInfo;
47 
48 import com.android.internal.annotations.VisibleForTesting;
49 import com.android.internal.app.IVoiceInteractor;
50 import com.android.internal.content.ReferrerIntent;
51 
52 import java.util.ArrayList;
53 import java.util.List;
54 import java.util.Objects;
55 
56 /**
57  * Request to launch an activity.
58  *
59  * @hide
60  */
61 public class LaunchActivityItem extends ClientTransactionItem {
62 
63     @NonNull
64     private final IBinder mActivityToken;
65 
66     // TODO(b/170729553): Mark this with @NonNull and final once @UnsupportedAppUsage removed.
67     //  We cannot do it now to avoid app compatibility regression.
68     @UnsupportedAppUsage
69     private Intent mIntent;
70 
71     // TODO(b/170729553): Mark this with @NonNull and final once @UnsupportedAppUsage removed.
72     //  We cannot do it now to avoid app compatibility regression.
73     @UnsupportedAppUsage
74     private ActivityInfo mInfo;
75 
76     @NonNull
77     private final Configuration mCurConfig;
78 
79     @NonNull
80     private final Configuration mOverrideConfig;
81 
82     @Nullable
83     private final String mReferrer;
84 
85     @Nullable
86     private final IVoiceInteractor mVoiceInteractor;
87 
88     @Nullable
89     private final Bundle mState;
90 
91     @Nullable
92     private final PersistableBundle mPersistentState;
93 
94     @Nullable
95     private final List<ResultInfo> mPendingResults;
96 
97     @Nullable
98     private final List<ReferrerIntent> mPendingNewIntents;
99 
100     @Nullable
101     private final SceneTransitionInfo mSceneTransitionInfo;
102 
103     @Nullable
104     private final ProfilerInfo mProfilerInfo;
105 
106     @NonNull
107     private final IBinder mAssistToken;
108 
109     @NonNull
110     private final IBinder mShareableActivityToken;
111 
112     @Nullable
113     private final IBinder mTaskFragmentToken;
114 
115     @NonNull
116     private final IBinder mInitialCallerInfoAccessToken;
117 
118     @NonNull
119     private final ActivityWindowInfo mActivityWindowInfo;
120 
121     /**
122      * It is only non-null if the process is the first time to launch activity. It is only an
123      * optimization for quick look up of the interface so the field is ignored for comparison.
124      */
125     @Nullable
126     private final IActivityClientController mActivityClientController;
127 
128     private final int mIdent;
129     private final int mDeviceId;
130     private final int mProcState;
131     private final boolean mIsForward;
132     private final boolean mLaunchedFromBubble;
133 
LaunchActivityItem(@onNull IBinder activityToken, @NonNull Intent intent, int ident, @NonNull ActivityInfo info, @NonNull Configuration curConfig, @NonNull Configuration overrideConfig, int deviceId, @Nullable String referrer, @Nullable IVoiceInteractor voiceInteractor, @ProcessState int procState, @Nullable Bundle state, @Nullable PersistableBundle persistentState, @Nullable List<ResultInfo> pendingResults, @Nullable List<ReferrerIntent> pendingNewIntents, @Nullable SceneTransitionInfo sceneTransitionInfo, boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken, @Nullable IActivityClientController activityClientController, @NonNull IBinder shareableActivityToken, boolean launchedFromBubble, @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken, @NonNull ActivityWindowInfo activityWindowInfo)134     public LaunchActivityItem(@NonNull IBinder activityToken, @NonNull Intent intent,
135             int ident, @NonNull ActivityInfo info, @NonNull Configuration curConfig,
136             @NonNull Configuration overrideConfig, int deviceId, @Nullable String referrer,
137             @Nullable IVoiceInteractor voiceInteractor, @ProcessState int procState,
138             @Nullable Bundle state, @Nullable PersistableBundle persistentState,
139             @Nullable List<ResultInfo> pendingResults,
140             @Nullable List<ReferrerIntent> pendingNewIntents,
141             @Nullable SceneTransitionInfo sceneTransitionInfo,
142             boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken,
143             @Nullable IActivityClientController activityClientController,
144             @NonNull IBinder shareableActivityToken, boolean launchedFromBubble,
145             @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken,
146             @NonNull ActivityWindowInfo activityWindowInfo) {
147         this(activityToken, ident, new Configuration(curConfig), new Configuration(overrideConfig),
148                 deviceId, referrer, voiceInteractor, procState,
149                 state != null ? new Bundle(state) : null,
150                 persistentState != null ? new PersistableBundle(persistentState) : null,
151                 pendingResults != null ? new ArrayList<>(pendingResults) : null,
152                 pendingNewIntents != null ? new ArrayList<>(pendingNewIntents) : null,
153                 sceneTransitionInfo, isForward,
154                 profilerInfo != null ? new ProfilerInfo(profilerInfo) : null,
155                 assistToken, activityClientController, shareableActivityToken, launchedFromBubble,
156                 taskFragmentToken, initialCallerInfoAccessToken,
157                 new ActivityWindowInfo(activityWindowInfo));
158         mIntent = new Intent(intent);
159         mInfo = new ActivityInfo(info);
160     }
161 
162     // TODO(b/170729553): Merge this constructor with previous one if no @UnsupportedAppUsage filed.
163     //  We cannot do it now to avoid app compatibility regression.
LaunchActivityItem(@onNull IBinder activityToken, int ident, @NonNull Configuration curConfig, @NonNull Configuration overrideConfig, int deviceId, @Nullable String referrer, @Nullable IVoiceInteractor voiceInteractor, @ProcessState int procState, @Nullable Bundle state, @Nullable PersistableBundle persistentState, @Nullable List<ResultInfo> pendingResults, @Nullable List<ReferrerIntent> pendingNewIntents, @Nullable SceneTransitionInfo sceneTransitionInfo, boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken, @Nullable IActivityClientController activityClientController, @NonNull IBinder shareableActivityToken, boolean launchedFromBubble, @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken, @NonNull ActivityWindowInfo activityWindowInfo)164     private LaunchActivityItem(@NonNull IBinder activityToken, int ident,
165             @NonNull Configuration curConfig,
166             @NonNull Configuration overrideConfig, int deviceId, @Nullable String referrer,
167             @Nullable IVoiceInteractor voiceInteractor, @ProcessState int procState,
168             @Nullable Bundle state, @Nullable PersistableBundle persistentState,
169             @Nullable List<ResultInfo> pendingResults,
170             @Nullable List<ReferrerIntent> pendingNewIntents,
171             @Nullable SceneTransitionInfo sceneTransitionInfo,
172             boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken,
173             @Nullable IActivityClientController activityClientController,
174             @NonNull IBinder shareableActivityToken, boolean launchedFromBubble,
175             @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken,
176             @NonNull ActivityWindowInfo activityWindowInfo) {
177         mActivityToken = activityToken;
178         mIdent = ident;
179         mCurConfig = curConfig;
180         mOverrideConfig = overrideConfig;
181         mDeviceId = deviceId;
182         mReferrer = referrer;
183         mVoiceInteractor = voiceInteractor;
184         mProcState = procState;
185         mState = state;
186         mPersistentState = persistentState;
187         mPendingResults = pendingResults;
188         mPendingNewIntents = pendingNewIntents;
189         mSceneTransitionInfo = sceneTransitionInfo;
190         mIsForward = isForward;
191         mProfilerInfo = profilerInfo;
192         mAssistToken = assistToken;
193         mActivityClientController = activityClientController;
194         mShareableActivityToken = shareableActivityToken;
195         mLaunchedFromBubble = launchedFromBubble;
196         mTaskFragmentToken = taskFragmentToken;
197         mInitialCallerInfoAccessToken = initialCallerInfoAccessToken;
198         mActivityWindowInfo = activityWindowInfo;
199     }
200 
201     @Override
preExecute(@onNull ClientTransactionHandler client)202     public void preExecute(@NonNull ClientTransactionHandler client) {
203         client.countLaunchingActivities(1);
204         client.updateProcessState(mProcState, false);
205         CompatibilityInfo.applyOverrideIfNeeded(mCurConfig);
206         CompatibilityInfo.applyOverrideIfNeeded(mOverrideConfig);
207         client.updatePendingConfiguration(mCurConfig);
208         if (mActivityClientController != null) {
209             ActivityClient.setActivityClientController(mActivityClientController);
210         }
211     }
212 
213     @Override
execute(@onNull ClientTransactionHandler client, @NonNull PendingTransactionActions pendingActions)214     public void execute(@NonNull ClientTransactionHandler client,
215             @NonNull PendingTransactionActions pendingActions) {
216         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
217         final ActivityClientRecord r = new ActivityClientRecord(mActivityToken, mIntent, mIdent,
218                 mInfo, mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
219                 mPendingResults, mPendingNewIntents, mSceneTransitionInfo, mIsForward,
220                 mProfilerInfo, client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
221                 mTaskFragmentToken, mInitialCallerInfoAccessToken, mActivityWindowInfo);
222         client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
223         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
224     }
225 
226     @Override
postExecute(@onNull ClientTransactionHandler client, @NonNull PendingTransactionActions pendingActions)227     public void postExecute(@NonNull ClientTransactionHandler client,
228             @NonNull PendingTransactionActions pendingActions) {
229         client.countLaunchingActivities(-1);
230     }
231 
232     @VisibleForTesting(visibility = PACKAGE)
233     @NonNull
234     @Override
getActivityToken()235     public IBinder getActivityToken() {
236         return mActivityToken;
237     }
238 
239     // Parcelable implementation
240 
241     /** Writes to Parcel. */
242     @Override
writeToParcel(@onNull Parcel dest, int flags)243     public void writeToParcel(@NonNull Parcel dest, int flags) {
244         dest.writeStrongBinder(mActivityToken);
245         dest.writeInt(mIdent);
246         dest.writeTypedObject(mCurConfig, flags);
247         dest.writeTypedObject(mOverrideConfig, flags);
248         dest.writeInt(mDeviceId);
249         dest.writeString(mReferrer);
250         dest.writeStrongInterface(mVoiceInteractor);
251         dest.writeInt(mProcState);
252         dest.writeBundle(mState);
253         dest.writePersistableBundle(mPersistentState);
254         dest.writeTypedList(mPendingResults, flags);
255         dest.writeTypedList(mPendingNewIntents, flags);
256         dest.writeTypedObject(mSceneTransitionInfo, flags);
257         dest.writeBoolean(mIsForward);
258         dest.writeTypedObject(mProfilerInfo, flags);
259         dest.writeStrongBinder(mAssistToken);
260         dest.writeStrongInterface(mActivityClientController);
261         dest.writeStrongBinder(mShareableActivityToken);
262         dest.writeBoolean(mLaunchedFromBubble);
263         dest.writeStrongBinder(mTaskFragmentToken);
264         dest.writeStrongBinder(mInitialCallerInfoAccessToken);
265         dest.writeTypedObject(mActivityWindowInfo, flags);
266 
267         dest.writeTypedObject(mIntent, flags);
268         dest.writeTypedObject(mInfo, flags);
269     }
270 
271     /** Reads from Parcel. */
LaunchActivityItem(@onNull Parcel in)272     private LaunchActivityItem(@NonNull Parcel in) {
273         this(in.readStrongBinder() /* activityToken */,
274                 in.readInt() /* ident */,
275                 requireNonNull(in.readTypedObject(Configuration.CREATOR)) /* curConfig */,
276                 requireNonNull(in.readTypedObject(Configuration.CREATOR)) /* overrideConfig */,
277                 in.readInt() /* deviceId */,
278                 in.readString() /* referrer */,
279                 IVoiceInteractor.Stub.asInterface(in.readStrongBinder()) /* voiceInteractor */,
280                 in.readInt() /* procState */,
281                 in.readBundle(in.getClass().getClassLoader()) /* state */,
282                 in.readPersistableBundle(in.getClass().getClassLoader()) /* persistentState */,
283                 in.createTypedArrayList(ResultInfo.CREATOR) /* pendingResults */,
284                 in.createTypedArrayList(ReferrerIntent.CREATOR) /* pendingNewIntents */,
285                 in.readTypedObject(SceneTransitionInfo.CREATOR) /* sceneTransitionInfo */,
286                 in.readBoolean() /* isForward */,
287                 in.readTypedObject(ProfilerInfo.CREATOR) /* profilerInfo */,
288                 in.readStrongBinder() /* assistToken */,
289                 IActivityClientController.Stub.asInterface(
290                         in.readStrongBinder()) /* activityClientController */,
291                 in.readStrongBinder() /* shareableActivityToken */,
292                 in.readBoolean() /* launchedFromBubble */,
293                 in.readStrongBinder() /* taskFragmentToken */,
294                 in.readStrongBinder() /* initialCallerInfoAccessToken */,
295                 requireNonNull(in.readTypedObject(ActivityWindowInfo.CREATOR))
296                 /* activityWindowInfo */
297         );
298         mIntent = in.readTypedObject(Intent.CREATOR);
299         mInfo = in.readTypedObject(ActivityInfo.CREATOR);
300     }
301 
302     public static final @NonNull Creator<LaunchActivityItem> CREATOR = new Creator<>() {
303         public LaunchActivityItem createFromParcel(@NonNull Parcel in) {
304             return new LaunchActivityItem(in);
305         }
306 
307         public LaunchActivityItem[] newArray(int size) {
308             return new LaunchActivityItem[size];
309         }
310     };
311 
312     @Override
equals(@ullable Object o)313     public boolean equals(@Nullable Object o) {
314         if (this == o) {
315             return true;
316         }
317         if (o == null || getClass() != o.getClass()) {
318             return false;
319         }
320         final LaunchActivityItem other = (LaunchActivityItem) o;
321         final boolean intentsEqual = (mIntent == null && other.mIntent == null)
322                 || (mIntent != null && mIntent.filterEquals(other.mIntent));
323         return intentsEqual
324                 && Objects.equals(mActivityToken, other.mActivityToken) && mIdent == other.mIdent
325                 && activityInfoEqual(other.mInfo) && Objects.equals(mCurConfig, other.mCurConfig)
326                 && Objects.equals(mOverrideConfig, other.mOverrideConfig)
327                 && mDeviceId == other.mDeviceId
328                 && Objects.equals(mReferrer, other.mReferrer)
329                 && mProcState == other.mProcState && areBundlesEqualRoughly(mState, other.mState)
330                 && areBundlesEqualRoughly(mPersistentState, other.mPersistentState)
331                 && Objects.equals(mPendingResults, other.mPendingResults)
332                 && Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
333                 && (mSceneTransitionInfo == null) == (other.mSceneTransitionInfo == null)
334                 && mIsForward == other.mIsForward
335                 && Objects.equals(mProfilerInfo, other.mProfilerInfo)
336                 && Objects.equals(mAssistToken, other.mAssistToken)
337                 && Objects.equals(mShareableActivityToken, other.mShareableActivityToken)
338                 && Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken)
339                 && Objects.equals(mInitialCallerInfoAccessToken,
340                         other.mInitialCallerInfoAccessToken)
341                 && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo);
342     }
343 
344     @Override
hashCode()345     public int hashCode() {
346         int result = 17;
347         result = 31 * result + Objects.hashCode(mActivityToken);
348         result = 31 * result + mIntent.filterHashCode();
349         result = 31 * result + mIdent;
350         result = 31 * result + Objects.hashCode(mCurConfig);
351         result = 31 * result + Objects.hashCode(mOverrideConfig);
352         result = 31 * result + mDeviceId;
353         result = 31 * result + Objects.hashCode(mReferrer);
354         result = 31 * result + Objects.hashCode(mProcState);
355         result = 31 * result + getRoughBundleHashCode(mState);
356         result = 31 * result + getRoughBundleHashCode(mPersistentState);
357         result = 31 * result + Objects.hashCode(mPendingResults);
358         result = 31 * result + Objects.hashCode(mPendingNewIntents);
359         result = 31 * result + (mSceneTransitionInfo != null ? 1 : 0);
360         result = 31 * result + (mIsForward ? 1 : 0);
361         result = 31 * result + Objects.hashCode(mProfilerInfo);
362         result = 31 * result + Objects.hashCode(mAssistToken);
363         result = 31 * result + Objects.hashCode(mShareableActivityToken);
364         result = 31 * result + Objects.hashCode(mTaskFragmentToken);
365         result = 31 * result + Objects.hashCode(mInitialCallerInfoAccessToken);
366         result = 31 * result + Objects.hashCode(mActivityWindowInfo);
367         return result;
368     }
369 
activityInfoEqual(@ullable ActivityInfo other)370     private boolean activityInfoEqual(@Nullable ActivityInfo other) {
371         if (mInfo == null) {
372             return other == null;
373         }
374         return other != null && mInfo.flags == other.flags
375                 && mInfo.getMaxAspectRatio() == other.getMaxAspectRatio()
376                 && Objects.equals(mInfo.launchToken, other.launchToken)
377                 && Objects.equals(mInfo.getComponentName(), other.getComponentName());
378     }
379 
380     /**
381      * This method may be used to compare a parceled item with another unparceled item, and the
382      * parceled bundle may contain customized class that will raise BadParcelableException when
383      * unparceling if a customized class loader is not set to the bundle. So the hash code is
384      * simply determined by the bundle is empty or not.
385      */
getRoughBundleHashCode(@ullable BaseBundle bundle)386     private static int getRoughBundleHashCode(@Nullable BaseBundle bundle) {
387         return (bundle == null || bundle.isDefinitelyEmpty()) ? 0 : 1;
388     }
389 
390     /** Compares the bundles without unparceling them (avoid BadParcelableException). */
areBundlesEqualRoughly(@ullable BaseBundle a, @Nullable BaseBundle b)391     private static boolean areBundlesEqualRoughly(@Nullable BaseBundle a, @Nullable BaseBundle b) {
392         return getRoughBundleHashCode(a) == getRoughBundleHashCode(b);
393     }
394 
395     @Override
toString()396     public String toString() {
397         return "LaunchActivityItem{activityToken=" + mActivityToken
398                 + ",intent=" + mIntent
399                 + ",ident=" + mIdent
400                 + ",info=" + mInfo
401                 + ",curConfig=" + mCurConfig
402                 + ",overrideConfig=" + mOverrideConfig
403                 + ",deviceId=" + mDeviceId
404                 + ",referrer=" + mReferrer
405                 + ",procState=" + mProcState
406                 + ",state=" + mState
407                 + ",persistentState=" + mPersistentState
408                 + ",pendingResults=" + mPendingResults
409                 + ",pendingNewIntents=" + mPendingNewIntents
410                 + ",sceneTransitionInfo=" + mSceneTransitionInfo
411                 + ",profilerInfo=" + mProfilerInfo
412                 + ",assistToken=" + mAssistToken
413                 + ",shareableActivityToken=" + mShareableActivityToken
414                 + ",activityWindowInfo=" + mActivityWindowInfo
415                 + "}";
416     }
417 }
418