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