content: /*
   * 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.ActivityTaskManager;
  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.
                  ActivityTaskManager.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();
              }
          }
      }
  }
  