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.app.ActivityThread.DEBUG_MEMORY_TRIM; 20 21 import android.app.ActivityClient; 22 import android.app.ActivityThread.ActivityClientRecord; 23 import android.os.Build; 24 import android.os.Bundle; 25 import android.os.PersistableBundle; 26 import android.os.TransactionTooLargeException; 27 import android.util.Log; 28 import android.util.LogWriter; 29 import android.util.Slog; 30 31 import com.android.internal.util.IndentingPrintWriter; 32 33 /** 34 * Container that has data pending to be used at later stages of 35 * {@link android.app.servertransaction.ClientTransaction}. 36 * An instance of this class is passed to each individual transaction item, so it can use some 37 * information from previous steps or add some for the following steps. 38 * 39 * @hide 40 */ 41 public class PendingTransactionActions { 42 private boolean mRestoreInstanceState; 43 private boolean mCallOnPostCreate; 44 private Bundle mOldState; 45 private StopInfo mStopInfo; 46 private boolean mReportRelaunchToWM; 47 PendingTransactionActions()48 public PendingTransactionActions() { 49 clear(); 50 } 51 52 /** Reset the state of the instance to default, non-initialized values. */ clear()53 public void clear() { 54 mRestoreInstanceState = false; 55 mCallOnPostCreate = false; 56 mOldState = null; 57 mStopInfo = null; 58 } 59 60 /** Getter */ shouldRestoreInstanceState()61 public boolean shouldRestoreInstanceState() { 62 return mRestoreInstanceState; 63 } 64 setRestoreInstanceState(boolean restoreInstanceState)65 public void setRestoreInstanceState(boolean restoreInstanceState) { 66 mRestoreInstanceState = restoreInstanceState; 67 } 68 69 /** Getter */ shouldCallOnPostCreate()70 public boolean shouldCallOnPostCreate() { 71 return mCallOnPostCreate; 72 } 73 setCallOnPostCreate(boolean callOnPostCreate)74 public void setCallOnPostCreate(boolean callOnPostCreate) { 75 mCallOnPostCreate = callOnPostCreate; 76 } 77 getOldState()78 public Bundle getOldState() { 79 return mOldState; 80 } 81 setOldState(Bundle oldState)82 public void setOldState(Bundle oldState) { 83 mOldState = oldState; 84 } 85 getStopInfo()86 public StopInfo getStopInfo() { 87 return mStopInfo; 88 } 89 setStopInfo(StopInfo stopInfo)90 public void setStopInfo(StopInfo stopInfo) { 91 mStopInfo = stopInfo; 92 } 93 94 /** 95 * Check if we should report an activity relaunch to WindowManager. We report back for every 96 * relaunch request to ActivityManager, but only for those that were actually finished to we 97 * report to WindowManager. 98 */ shouldReportRelaunchToWindowManager()99 public boolean shouldReportRelaunchToWindowManager() { 100 return mReportRelaunchToWM; 101 } 102 103 /** 104 * Set if we should report an activity relaunch to WindowManager. We report back for every 105 * relaunch request to ActivityManager, but only for those that were actually finished we report 106 * to WindowManager. 107 */ setReportRelaunchToWindowManager(boolean reportToWm)108 public void setReportRelaunchToWindowManager(boolean reportToWm) { 109 mReportRelaunchToWM = reportToWm; 110 } 111 112 /** Reports to server about activity stop. */ 113 public static class StopInfo implements Runnable { 114 private static final String TAG = "ActivityStopInfo"; 115 116 private ActivityClientRecord mActivity; 117 private Bundle mState; 118 private PersistableBundle mPersistentState; 119 private CharSequence mDescription; 120 setActivity(ActivityClientRecord activity)121 public void setActivity(ActivityClientRecord activity) { 122 mActivity = activity; 123 } 124 setState(Bundle state)125 public void setState(Bundle state) { 126 mState = state; 127 } 128 setPersistentState(PersistableBundle persistentState)129 public void setPersistentState(PersistableBundle persistentState) { 130 mPersistentState = persistentState; 131 } 132 setDescription(CharSequence description)133 public void setDescription(CharSequence description) { 134 mDescription = description; 135 } 136 137 @Override run()138 public void run() { 139 // Tell activity manager we have been stopped. 140 try { 141 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + mActivity); 142 // TODO(lifecycler): Use interface callback instead of AMS. 143 ActivityClient.getInstance().activityStopped( 144 mActivity.token, mState, mPersistentState, mDescription); 145 } catch (RuntimeException ex) { 146 // Dump statistics about bundle to help developers debug 147 final LogWriter writer = new LogWriter(Log.WARN, TAG); 148 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 149 pw.println("Bundle stats:"); 150 Bundle.dumpStats(pw, mState); 151 pw.println("PersistableBundle stats:"); 152 Bundle.dumpStats(pw, mPersistentState); 153 154 if (ex.getCause() instanceof TransactionTooLargeException 155 && mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { 156 Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex); 157 return; 158 } 159 throw ex; 160 } 161 } 162 } 163 } 164