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