161 lines
5.3 KiB
Java
161 lines
5.3 KiB
Java
![]() |
/*
|
||
|
* 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.ActivityClient;
|
||
|
import android.app.ActivityThread.ActivityClientRecord;
|
||
|
import android.os.Build;
|
||
|
import android.os.Bundle;
|
||
|
import android.os.PersistableBundle;
|
||
|
import android.os.TransactionTooLargeException;
|
||
|
import android.util.Log;
|
||
|
import android.util.Slog;
|
||
|
|
||
|
import com.android.internal.util.IndentingPrintWriter;
|
||
|
|
||
|
import java.io.StringWriter;
|
||
|
|
||
|
/**
|
||
|
* 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;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/** 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;
|
||
|
}
|
||
|
|
||
|
private String collectBundleStates() {
|
||
|
final StringWriter writer = new StringWriter();
|
||
|
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
|
||
|
pw.println("Bundle stats:");
|
||
|
Bundle.dumpStats(pw, mState);
|
||
|
pw.println("PersistableBundle stats:");
|
||
|
Bundle.dumpStats(pw, mPersistentState);
|
||
|
return writer.toString().stripTrailing();
|
||
|
}
|
||
|
|
||
|
@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.
|
||
|
ActivityClient.getInstance().activityStopped(
|
||
|
mActivity.token, mState, mPersistentState, mDescription);
|
||
|
} catch (RuntimeException runtimeException) {
|
||
|
// Collect the statistics about bundle
|
||
|
final String bundleStats = collectBundleStates();
|
||
|
|
||
|
RuntimeException ex = runtimeException;
|
||
|
if (ex.getCause() instanceof TransactionTooLargeException) {
|
||
|
// Embed the stats into exception message to help developers debug if the
|
||
|
// transaction size is too large.
|
||
|
final String message = ex.getMessage() + "\n" + bundleStats;
|
||
|
ex = new RuntimeException(message, ex.getCause());
|
||
|
if (mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
|
||
|
Log.e(TAG, "App sent too much data in instance state, so it was ignored",
|
||
|
ex);
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
// Otherwise, dump the stats anyway.
|
||
|
Log.w(TAG, bundleStats);
|
||
|
}
|
||
|
throw ex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|