| /* |
| * Copyright 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app.servertransaction; |
| |
| import static android.app.ActivityThread.DEBUG_MEMORY_TRIM; |
| |
| import android.app.ActivityManager; |
| import android.app.ActivityThread.ActivityClientRecord; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.os.PersistableBundle; |
| import android.os.RemoteException; |
| import android.os.TransactionTooLargeException; |
| import android.util.Log; |
| import android.util.LogWriter; |
| import android.util.Slog; |
| |
| import com.android.internal.util.IndentingPrintWriter; |
| |
| /** |
| * Container that has data pending to be used at later stages of |
| * {@link android.app.servertransaction.ClientTransaction}. |
| * An instance of this class is passed to each individual transaction item, so it can use some |
| * information from previous steps or add some for the following steps. |
| * |
| * @hide |
| */ |
| public class PendingTransactionActions { |
| private boolean mRestoreInstanceState; |
| private boolean mCallOnPostCreate; |
| private Bundle mOldState; |
| private StopInfo mStopInfo; |
| private boolean mReportRelaunchToWM; |
| |
| public PendingTransactionActions() { |
| clear(); |
| } |
| |
| /** Reset the state of the instance to default, non-initialized values. */ |
| public void clear() { |
| mRestoreInstanceState = false; |
| mCallOnPostCreate = false; |
| mOldState = null; |
| mStopInfo = null; |
| } |
| |
| /** Getter */ |
| public boolean shouldRestoreInstanceState() { |
| return mRestoreInstanceState; |
| } |
| |
| public void setRestoreInstanceState(boolean restoreInstanceState) { |
| mRestoreInstanceState = restoreInstanceState; |
| } |
| |
| /** Getter */ |
| public boolean shouldCallOnPostCreate() { |
| return mCallOnPostCreate; |
| } |
| |
| public void setCallOnPostCreate(boolean callOnPostCreate) { |
| mCallOnPostCreate = callOnPostCreate; |
| } |
| |
| public Bundle getOldState() { |
| return mOldState; |
| } |
| |
| public void setOldState(Bundle oldState) { |
| mOldState = oldState; |
| } |
| |
| public StopInfo getStopInfo() { |
| return mStopInfo; |
| } |
| |
| public void setStopInfo(StopInfo stopInfo) { |
| mStopInfo = stopInfo; |
| } |
| |
| /** |
| * Check if we should report an activity relaunch to WindowManager. We report back for every |
| * relaunch request to ActivityManager, but only for those that were actually finished to we |
| * report to WindowManager. |
| */ |
| public boolean shouldReportRelaunchToWindowManager() { |
| return mReportRelaunchToWM; |
| } |
| |
| /** |
| * Set if we should report an activity relaunch to WindowManager. We report back for every |
| * relaunch request to ActivityManager, but only for those that were actually finished we report |
| * to WindowManager. |
| */ |
| public void setReportRelaunchToWindowManager(boolean reportToWm) { |
| mReportRelaunchToWM = reportToWm; |
| } |
| |
| /** Reports to server about activity stop. */ |
| public static class StopInfo implements Runnable { |
| private static final String TAG = "ActivityStopInfo"; |
| |
| private ActivityClientRecord mActivity; |
| private Bundle mState; |
| private PersistableBundle mPersistentState; |
| private CharSequence mDescription; |
| |
| public void setActivity(ActivityClientRecord activity) { |
| mActivity = activity; |
| } |
| |
| public void setState(Bundle state) { |
| mState = state; |
| } |
| |
| public void setPersistentState(PersistableBundle persistentState) { |
| mPersistentState = persistentState; |
| } |
| |
| public void setDescription(CharSequence description) { |
| mDescription = description; |
| } |
| |
| @Override |
| public void run() { |
| // Tell activity manager we have been stopped. |
| try { |
| if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + mActivity); |
| // TODO(lifecycler): Use interface callback instead of AMS. |
| ActivityManager.getService().activityStopped( |
| mActivity.token, mState, mPersistentState, mDescription); |
| } catch (RemoteException ex) { |
| // Dump statistics about bundle to help developers debug |
| final LogWriter writer = new LogWriter(Log.WARN, TAG); |
| final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); |
| pw.println("Bundle stats:"); |
| Bundle.dumpStats(pw, mState); |
| pw.println("PersistableBundle stats:"); |
| Bundle.dumpStats(pw, mPersistentState); |
| |
| if (ex instanceof TransactionTooLargeException |
| && mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { |
| Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex); |
| return; |
| } |
| throw ex.rethrowFromSystemServer(); |
| } |
| } |
| } |
| } |