Home | History | Annotate | Download | only in servertransaction
      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
     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