LaunchActivityItem.java revision 770c4030691f11ca36ef0028a336a27eda2049ef
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
17package android.app.servertransaction;
18
19import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
20
21import android.app.ActivityThread.ActivityClientRecord;
22import android.app.ClientTransactionHandler;
23import android.app.ProfilerInfo;
24import android.app.ResultInfo;
25import android.content.Intent;
26import android.content.pm.ActivityInfo;
27import android.content.res.CompatibilityInfo;
28import android.content.res.Configuration;
29import android.os.BaseBundle;
30import android.os.Bundle;
31import android.os.IBinder;
32import android.os.Parcel;
33import android.os.PersistableBundle;
34import android.os.Trace;
35
36import com.android.internal.app.IVoiceInteractor;
37import com.android.internal.content.ReferrerIntent;
38
39import java.util.List;
40import java.util.Objects;
41
42/**
43 * Request to launch an activity.
44 * @hide
45 */
46public class LaunchActivityItem extends ClientTransactionItem {
47
48    private Intent mIntent;
49    private int mIdent;
50    private ActivityInfo mInfo;
51    private Configuration mCurConfig;
52    private Configuration mOverrideConfig;
53    private CompatibilityInfo mCompatInfo;
54    private String mReferrer;
55    private IVoiceInteractor mVoiceInteractor;
56    private int mProcState;
57    private Bundle mState;
58    private PersistableBundle mPersistentState;
59    private List<ResultInfo> mPendingResults;
60    private List<ReferrerIntent> mPendingNewIntents;
61    private boolean mIsForward;
62    private ProfilerInfo mProfilerInfo;
63
64    @Override
65    public void preExecute(ClientTransactionHandler client, IBinder token) {
66        client.updateProcessState(mProcState, false);
67        client.updatePendingConfiguration(mCurConfig);
68    }
69
70    @Override
71    public void execute(ClientTransactionHandler client, IBinder token,
72            PendingTransactionActions pendingActions) {
73        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
74        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
75                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
76                mPendingResults, mPendingNewIntents, mIsForward,
77                mProfilerInfo, client);
78        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
79        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
80    }
81
82
83    // ObjectPoolItem implementation
84
85    private LaunchActivityItem() {}
86
87    /** Obtain an instance initialized with provided params. */
88    public static LaunchActivityItem obtain(Intent intent, int ident, ActivityInfo info,
89            Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo,
90            String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
91            PersistableBundle persistentState, List<ResultInfo> pendingResults,
92            List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo) {
93        LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
94        if (instance == null) {
95            instance = new LaunchActivityItem();
96        }
97        setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
98                voiceInteractor, procState, state, persistentState, pendingResults,
99                pendingNewIntents, isForward, profilerInfo);
100
101        return instance;
102    }
103
104    @Override
105    public void recycle() {
106        setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
107                false, null);
108        ObjectPool.recycle(this);
109    }
110
111
112    // Parcelable implementation
113
114    /** Write from Parcel. */
115    @Override
116    public void writeToParcel(Parcel dest, int flags) {
117        dest.writeTypedObject(mIntent, flags);
118        dest.writeInt(mIdent);
119        dest.writeTypedObject(mInfo, flags);
120        dest.writeTypedObject(mCurConfig, flags);
121        dest.writeTypedObject(mOverrideConfig, flags);
122        dest.writeTypedObject(mCompatInfo, flags);
123        dest.writeString(mReferrer);
124        dest.writeStrongInterface(mVoiceInteractor);
125        dest.writeInt(mProcState);
126        dest.writeBundle(mState);
127        dest.writePersistableBundle(mPersistentState);
128        dest.writeTypedList(mPendingResults, flags);
129        dest.writeTypedList(mPendingNewIntents, flags);
130        dest.writeBoolean(mIsForward);
131        dest.writeTypedObject(mProfilerInfo, flags);
132    }
133
134    /** Read from Parcel. */
135    private LaunchActivityItem(Parcel in) {
136        setValues(this, in.readTypedObject(Intent.CREATOR), in.readInt(),
137                in.readTypedObject(ActivityInfo.CREATOR), in.readTypedObject(Configuration.CREATOR),
138                in.readTypedObject(Configuration.CREATOR),
139                in.readTypedObject(CompatibilityInfo.CREATOR), in.readString(),
140                IVoiceInteractor.Stub.asInterface(in.readStrongBinder()), in.readInt(),
141                in.readBundle(getClass().getClassLoader()),
142                in.readPersistableBundle(getClass().getClassLoader()),
143                in.createTypedArrayList(ResultInfo.CREATOR),
144                in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(),
145                in.readTypedObject(ProfilerInfo.CREATOR));
146    }
147
148    public static final Creator<LaunchActivityItem> CREATOR =
149            new Creator<LaunchActivityItem>() {
150        public LaunchActivityItem createFromParcel(Parcel in) {
151            return new LaunchActivityItem(in);
152        }
153
154        public LaunchActivityItem[] newArray(int size) {
155            return new LaunchActivityItem[size];
156        }
157    };
158
159    @Override
160    public boolean equals(Object o) {
161        if (this == o) {
162            return true;
163        }
164        if (o == null || getClass() != o.getClass()) {
165            return false;
166        }
167        final LaunchActivityItem other = (LaunchActivityItem) o;
168        final boolean intentsEqual = (mIntent == null && other.mIntent == null)
169                || (mIntent != null && mIntent.filterEquals(other.mIntent));
170        return intentsEqual && mIdent == other.mIdent
171                && activityInfoEqual(other.mInfo) && Objects.equals(mCurConfig, other.mCurConfig)
172                && Objects.equals(mOverrideConfig, other.mOverrideConfig)
173                && Objects.equals(mCompatInfo, other.mCompatInfo)
174                && Objects.equals(mReferrer, other.mReferrer)
175                && mProcState == other.mProcState && areBundlesEqual(mState, other.mState)
176                && areBundlesEqual(mPersistentState, other.mPersistentState)
177                && Objects.equals(mPendingResults, other.mPendingResults)
178                && Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
179                && mIsForward == other.mIsForward
180                && Objects.equals(mProfilerInfo, other.mProfilerInfo);
181    }
182
183    @Override
184    public int hashCode() {
185        int result = 17;
186        result = 31 * result + mIntent.filterHashCode();
187        result = 31 * result + mIdent;
188        result = 31 * result + Objects.hashCode(mCurConfig);
189        result = 31 * result + Objects.hashCode(mOverrideConfig);
190        result = 31 * result + Objects.hashCode(mCompatInfo);
191        result = 31 * result + Objects.hashCode(mReferrer);
192        result = 31 * result + Objects.hashCode(mProcState);
193        result = 31 * result + (mState != null ? mState.size() : 0);
194        result = 31 * result + (mPersistentState != null ? mPersistentState.size() : 0);
195        result = 31 * result + Objects.hashCode(mPendingResults);
196        result = 31 * result + Objects.hashCode(mPendingNewIntents);
197        result = 31 * result + (mIsForward ? 1 : 0);
198        result = 31 * result + Objects.hashCode(mProfilerInfo);
199        return result;
200    }
201
202    private boolean activityInfoEqual(ActivityInfo other) {
203        if (mInfo == null) {
204            return other == null;
205        }
206        return other != null && mInfo.flags == other.flags
207                && mInfo.maxAspectRatio == other.maxAspectRatio
208                && Objects.equals(mInfo.launchToken, other.launchToken)
209                && Objects.equals(mInfo.getComponentName(), other.getComponentName());
210    }
211
212    private static boolean areBundlesEqual(BaseBundle extras, BaseBundle newExtras) {
213        if (extras == null || newExtras == null) {
214            return extras == newExtras;
215        }
216
217        if (extras.size() != newExtras.size()) {
218            return false;
219        }
220
221        for (String key : extras.keySet()) {
222            if (key != null) {
223                final Object value = extras.get(key);
224                final Object newValue = newExtras.get(key);
225                if (!Objects.equals(value, newValue)) {
226                    return false;
227                }
228            }
229        }
230        return true;
231    }
232
233    @Override
234    public String toString() {
235        return "LaunchActivityItem{intent=" + mIntent + ",ident=" + mIdent + ",info=" + mInfo
236                + ",curConfig=" + mCurConfig + ",overrideConfig=" + mOverrideConfig
237                + ",referrer=" + mReferrer + ",procState=" + mProcState + ",state=" + mState
238                + ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
239                + ",pendingNewIntents=" + mPendingNewIntents + ",profilerInfo=" + mProfilerInfo
240                + "}";
241    }
242
243    // Using the same method to set and clear values to make sure we don't forget anything
244    private static void setValues(LaunchActivityItem instance, Intent intent, int ident,
245            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
246            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
247            int procState, Bundle state, PersistableBundle persistentState,
248            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
249            boolean isForward, ProfilerInfo profilerInfo) {
250        instance.mIntent = intent;
251        instance.mIdent = ident;
252        instance.mInfo = info;
253        instance.mCurConfig = curConfig;
254        instance.mOverrideConfig = overrideConfig;
255        instance.mCompatInfo = compatInfo;
256        instance.mReferrer = referrer;
257        instance.mVoiceInteractor = voiceInteractor;
258        instance.mProcState = procState;
259        instance.mState = state;
260        instance.mPersistentState = persistentState;
261        instance.mPendingResults = pendingResults;
262        instance.mPendingNewIntents = pendingNewIntents;
263        instance.mIsForward = isForward;
264        instance.mProfilerInfo = profilerInfo;
265    }
266}
267