Merge "Add an app stopped state parameter to ApplicationStartInfo" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 2d03be7..301dbfa 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -5329,6 +5329,7 @@
method public int getStartType();
method public int getStartupState();
method @NonNull public java.util.Map<java.lang.Integer,java.lang.Long> getStartupTimestamps();
+ method @FlaggedApi("android.content.pm.stay_stopped") public boolean wasForceStopped();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationStartInfo> CREATOR;
field public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2; // 0x2
diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java
index c6712c0..3715c6e 100644
--- a/core/java/android/app/ApplicationStartInfo.java
+++ b/core/java/android/app/ApplicationStartInfo.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.icu.text.SimpleDateFormat;
import android.os.Parcel;
import android.os.Parcelable;
@@ -249,7 +250,7 @@
private @StartType int mStartType;
/**
- * @see #getStartIntent
+ * @see #getIntent
*/
private Intent mStartIntent;
@@ -259,6 +260,11 @@
private @LaunchMode int mLaunchMode;
/**
+ * @see #wasForceStopped()
+ */
+ private boolean mWasForceStopped;
+
+ /**
* @hide *
*/
@IntDef(
@@ -427,6 +433,15 @@
}
/**
+ * @see #wasForceStopped()
+ * @param wasForceStopped whether the app had been force-stopped in the past
+ * @hide
+ */
+ public void setForceStopped(boolean wasForceStopped) {
+ mWasForceStopped = wasForceStopped;
+ }
+
+ /**
* Current state of startup.
*
* Can be used to determine whether the object will have additional fields added as it may be
@@ -578,6 +593,20 @@
return mLaunchMode;
}
+ /**
+ * Informs whether this is the first process launch for an app since it was
+ * {@link ApplicationInfo#FLAG_STOPPED force-stopped} for some reason.
+ * This allows the app to know if it should re-register for any alarms, jobs and other callbacks
+ * that were cleared when the app was force-stopped.
+ *
+ * @return {@code true} if this is the first process launch of the app after having been
+ * stopped, {@code false} otherwise.
+ */
+ @FlaggedApi(android.content.pm.Flags.FLAG_STAY_STOPPED)
+ public boolean wasForceStopped() {
+ return mWasForceStopped;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -603,6 +632,7 @@
dest.writeInt(mStartType);
dest.writeParcelable(mStartIntent, flags);
dest.writeInt(mLaunchMode);
+ dest.writeBoolean(mWasForceStopped);
}
/** @hide */
@@ -622,6 +652,7 @@
mStartType = other.mStartType;
mStartIntent = other.mStartIntent;
mLaunchMode = other.mLaunchMode;
+ mWasForceStopped = other.mWasForceStopped;
}
private ApplicationStartInfo(@NonNull Parcel in) {
@@ -643,6 +674,7 @@
mStartIntent =
in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class);
mLaunchMode = in.readInt();
+ mWasForceStopped = in.readBoolean();
}
private static String intern(@Nullable String source) {
@@ -720,6 +752,7 @@
intentOut.close();
}
proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode);
+ proto.write(ApplicationStartInfoProto.WAS_FORCE_STOPPED, mWasForceStopped);
proto.end(token);
}
@@ -799,6 +832,10 @@
case (int) ApplicationStartInfoProto.LAUNCH_MODE:
mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE);
break;
+ case (int) ApplicationStartInfoProto.WAS_FORCE_STOPPED:
+ mWasForceStopped = proto.readBoolean(
+ ApplicationStartInfoProto.WAS_FORCE_STOPPED);
+ break;
}
}
proto.end(token);
@@ -823,6 +860,7 @@
.append(" reason=").append(reasonToString(mReason))
.append(" startType=").append(startTypeToString(mStartType))
.append(" launchMode=").append(mLaunchMode)
+ .append(" wasForceStopped=").append(mWasForceStopped)
.append('\n');
if (mStartIntent != null) {
sb.append(" intent=").append(mStartIntent.toString())
@@ -878,7 +916,7 @@
&& mDefiningUid == o.mDefiningUid && mReason == o.mReason
&& mStartupState == o.mStartupState && mStartType == o.mStartType
&& mLaunchMode == o.mLaunchMode && TextUtils.equals(mProcessName, o.mProcessName)
- && timestampsEquals(o);
+ && timestampsEquals(o) && mWasForceStopped == o.mWasForceStopped;
}
@Override
diff --git a/core/proto/android/app/appstartinfo.proto b/core/proto/android/app/appstartinfo.proto
index 8c33041..d9ed911 100644
--- a/core/proto/android/app/appstartinfo.proto
+++ b/core/proto/android/app/appstartinfo.proto
@@ -39,4 +39,5 @@
optional AppStartStartType start_type = 9;
optional bytes start_intent = 10;
optional AppStartLaunchMode launch_mode = 11;
+ optional bool was_force_stopped = 12;
}
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index c857235..1dc384d 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -383,6 +383,11 @@
start.setDefiningUid(definingUid > 0 ? definingUid : app.info.uid);
start.setProcessName(app.processName);
start.setPackageName(app.info.packageName);
+ if (android.content.pm.Flags.stayStopped()) {
+ // TODO: Verify this is created at the right time to have the correct force-stopped
+ // state in the ProcessRecord. Also use the WindowProcessRecord if activity.
+ start.setForceStopped(app.wasForceStopped());
+ }
}
void reportApplicationOnCreateTimeNanos(ProcessRecord app, long timeNs) {