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.app.ActivityThread.ActivityClientRecord; 22 import android.app.ClientTransactionHandler; 23 import android.app.ProfilerInfo; 24 import android.app.ResultInfo; 25 import android.content.Intent; 26 import android.content.pm.ActivityInfo; 27 import android.content.res.CompatibilityInfo; 28 import android.content.res.Configuration; 29 import android.os.BaseBundle; 30 import android.os.Bundle; 31 import android.os.IBinder; 32 import android.os.Parcel; 33 import android.os.PersistableBundle; 34 import android.os.Trace; 35 36 import com.android.internal.app.IVoiceInteractor; 37 import com.android.internal.content.ReferrerIntent; 38 39 import java.util.List; 40 import java.util.Objects; 41 42 /** 43 * Request to launch an activity. 44 * @hide 45 */ 46 public 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 preExecute(ClientTransactionHandler client, IBinder token)65 public void preExecute(ClientTransactionHandler client, IBinder token) { 66 client.updateProcessState(mProcState, false); 67 client.updatePendingConfiguration(mCurConfig); 68 } 69 70 @Override execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)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 LaunchActivityItem()85 private LaunchActivityItem() {} 86 87 /** 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, boolean isForward, ProfilerInfo profilerInfo)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 recycle()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 writeToParcel(Parcel dest, int flags)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. */ LaunchActivityItem(Parcel in)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 equals(Object o)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 hashCode()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 activityInfoEqual(ActivityInfo other)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 areBundlesEqual(BaseBundle extras, BaseBundle newExtras)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 toString()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 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, boolean isForward, ProfilerInfo profilerInfo)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