Merge "Use descriptive exception for FGS start timeout" into sc-dev
This commit is contained in:
@@ -236,12 +236,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
final class RemoteServiceException extends AndroidRuntimeException {
|
|
||||||
public RemoteServiceException(String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This manages the execution of the main thread in an
|
* This manages the execution of the main thread in an
|
||||||
* application process, scheduling and executing activities,
|
* application process, scheduling and executing activities,
|
||||||
@@ -1274,8 +1268,9 @@ public final class ActivityThread extends ClientTransactionHandler
|
|||||||
sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
|
sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scheduleCrash(String msg) {
|
@Override
|
||||||
sendMessage(H.SCHEDULE_CRASH, msg);
|
public void scheduleCrash(String msg, int typeId) {
|
||||||
|
sendMessage(H.SCHEDULE_CRASH, msg, typeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
|
public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
|
||||||
@@ -1892,6 +1887,17 @@ public final class ActivityThread extends ClientTransactionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void throwRemoteServiceException(String message, int typeId) {
|
||||||
|
// Use a switch to ensure all the type IDs are unique.
|
||||||
|
switch (typeId) {
|
||||||
|
case ForegroundServiceDidNotStartInTimeException.TYPE_ID: // 1
|
||||||
|
throw new ForegroundServiceDidNotStartInTimeException(message);
|
||||||
|
case RemoteServiceException.TYPE_ID: // 0
|
||||||
|
default:
|
||||||
|
throw new RemoteServiceException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class H extends Handler {
|
class H extends Handler {
|
||||||
public static final int BIND_APPLICATION = 110;
|
public static final int BIND_APPLICATION = 110;
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
@@ -2105,7 +2111,8 @@ public final class ActivityThread extends ClientTransactionHandler
|
|||||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||||
break;
|
break;
|
||||||
case SCHEDULE_CRASH:
|
case SCHEDULE_CRASH:
|
||||||
throw new RemoteServiceException((String)msg.obj);
|
throwRemoteServiceException((String) msg.obj, msg.arg1);
|
||||||
|
break;
|
||||||
case DUMP_HEAP:
|
case DUMP_HEAP:
|
||||||
handleDumpHeap((DumpHeapData) msg.obj);
|
handleDumpHeap((DumpHeapData) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used to crash an app process when it didn't call {@link Service#startForeground}
|
||||||
|
* in time after the service was started with
|
||||||
|
* {@link android.content.Context#startForegroundService}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class ForegroundServiceDidNotStartInTimeException extends RemoteServiceException {
|
||||||
|
/** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
|
||||||
|
public static final int TYPE_ID = 1;
|
||||||
|
|
||||||
|
public ForegroundServiceDidNotStartInTimeException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -321,6 +321,8 @@ interface IActivityManager {
|
|||||||
boolean isTopActivityImmersive();
|
boolean isTopActivityImmersive();
|
||||||
void crashApplication(int uid, int initialPid, in String packageName, int userId,
|
void crashApplication(int uid, int initialPid, in String packageName, int userId,
|
||||||
in String message, boolean force);
|
in String message, boolean force);
|
||||||
|
void crashApplicationWithType(int uid, int initialPid, in String packageName, int userId,
|
||||||
|
in String message, boolean force, int exceptionTypeId);
|
||||||
/** @deprecated -- use getProviderMimeTypeAsync */
|
/** @deprecated -- use getProviderMimeTypeAsync */
|
||||||
@UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
|
@UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
|
||||||
"Use {@link android.content.ContentResolver#getType} public API instead.")
|
"Use {@link android.content.ContentResolver#getType} public API instead.")
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ oneway interface IApplicationThread {
|
|||||||
void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
|
void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
|
||||||
void scheduleSuicide();
|
void scheduleSuicide();
|
||||||
void dispatchPackageBroadcast(int cmd, in String[] packages);
|
void dispatchPackageBroadcast(int cmd, in String[] packages);
|
||||||
void scheduleCrash(in String msg);
|
void scheduleCrash(in String msg, int typeId);
|
||||||
void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
|
void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
|
||||||
in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
|
in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
|
||||||
void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
|
void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
|
||||||
|
|||||||
38
core/java/android/app/RemoteServiceException.java
Normal file
38
core/java/android/app/RemoteServiceException.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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;
|
||||||
|
|
||||||
|
import android.util.AndroidRuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used by {@link ActivityThread} to crash an app process.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class RemoteServiceException extends AndroidRuntimeException {
|
||||||
|
/**
|
||||||
|
* The type ID passed to {@link IApplicationThread#scheduleCrash}.
|
||||||
|
*
|
||||||
|
* Assign a unique ID to each subclass. See the above method for the numbers that are already
|
||||||
|
* taken.
|
||||||
|
*/
|
||||||
|
public static final int TYPE_ID = 0;
|
||||||
|
|
||||||
|
public RemoteServiceException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -531,7 +531,7 @@ public class TransactionParcelTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void scheduleCrash(String s) throws RemoteException {
|
public void scheduleCrash(String s, int i) throws RemoteException {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import android.app.ActivityManagerInternal;
|
|||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
|
import android.app.ForegroundServiceDidNotStartInTimeException;
|
||||||
import android.app.ForegroundServiceStartNotAllowedException;
|
import android.app.ForegroundServiceStartNotAllowedException;
|
||||||
import android.app.IApplicationThread;
|
import android.app.IApplicationThread;
|
||||||
import android.app.IServiceConnection;
|
import android.app.IServiceConnection;
|
||||||
@@ -4988,9 +4989,10 @@ public final class ActiveServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
|
void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
|
||||||
mAm.crashApplication(app.uid, app.getPid(), app.info.packageName, app.userId,
|
mAm.crashApplicationWithType(app.uid, app.getPid(), app.info.packageName, app.userId,
|
||||||
"Context.startForegroundService() did not then call Service.startForeground(): "
|
"Context.startForegroundService() did not then call Service.startForeground(): "
|
||||||
+ serviceRecord, false /*force*/);
|
+ serviceRecord, false /*force*/,
|
||||||
|
ForegroundServiceDidNotStartInTimeException.TYPE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
|
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ import android.app.PendingIntent;
|
|||||||
import android.app.ProcessMemoryState;
|
import android.app.ProcessMemoryState;
|
||||||
import android.app.ProfilerInfo;
|
import android.app.ProfilerInfo;
|
||||||
import android.app.PropertyInvalidatedCache;
|
import android.app.PropertyInvalidatedCache;
|
||||||
|
import android.app.RemoteServiceException;
|
||||||
import android.app.SyncNotedAppOp;
|
import android.app.SyncNotedAppOp;
|
||||||
import android.app.WaitResult;
|
import android.app.WaitResult;
|
||||||
import android.app.backup.BackupManager.OperationType;
|
import android.app.backup.BackupManager.OperationType;
|
||||||
@@ -2935,6 +2936,13 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
@Override
|
@Override
|
||||||
public void crashApplication(int uid, int initialPid, String packageName, int userId,
|
public void crashApplication(int uid, int initialPid, String packageName, int userId,
|
||||||
String message, boolean force) {
|
String message, boolean force) {
|
||||||
|
crashApplicationWithType(uid, initialPid, packageName, userId, message, force,
|
||||||
|
RemoteServiceException.TYPE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void crashApplicationWithType(int uid, int initialPid, String packageName, int userId,
|
||||||
|
String message, boolean force, int exceptionTypeId) {
|
||||||
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
|
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
String msg = "Permission Denial: crashApplication() from pid="
|
String msg = "Permission Denial: crashApplication() from pid="
|
||||||
@@ -2947,7 +2955,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId,
|
mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId,
|
||||||
message, force);
|
message, force, exceptionTypeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ class AppErrors {
|
|||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
|
void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
|
||||||
String message, boolean force) {
|
String message, boolean force, int exceptionTypeId) {
|
||||||
ProcessRecord proc = null;
|
ProcessRecord proc = null;
|
||||||
|
|
||||||
// Figure out which process to kill. We don't trust that initialPid
|
// Figure out which process to kill. We don't trust that initialPid
|
||||||
@@ -518,7 +518,7 @@ class AppErrors {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc.scheduleCrashLocked(message);
|
proc.scheduleCrashLocked(message, exceptionTypeId);
|
||||||
if (force) {
|
if (force) {
|
||||||
// If the app is responsive, the scheduled crash will happen as expected
|
// If the app is responsive, the scheduled crash will happen as expected
|
||||||
// and then the delayed summary kill will be a no-op.
|
// and then the delayed summary kill will be a no-op.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.app.ApplicationExitInfo;
|
|||||||
import android.app.ApplicationExitInfo.Reason;
|
import android.app.ApplicationExitInfo.Reason;
|
||||||
import android.app.ApplicationExitInfo.SubReason;
|
import android.app.ApplicationExitInfo.SubReason;
|
||||||
import android.app.IApplicationThread;
|
import android.app.IApplicationThread;
|
||||||
|
import android.app.RemoteServiceException;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.ProcessInfo;
|
import android.content.pm.ProcessInfo;
|
||||||
import android.content.pm.VersionedPackage;
|
import android.content.pm.VersionedPackage;
|
||||||
@@ -949,6 +950,21 @@ class ProcessRecord implements WindowProcessListener {
|
|||||||
|
|
||||||
@GuardedBy("mService")
|
@GuardedBy("mService")
|
||||||
void scheduleCrashLocked(String message) {
|
void scheduleCrashLocked(String message) {
|
||||||
|
scheduleCrashLocked(message, RemoteServiceException.TYPE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let an app process throw an exception on a binder thread, which typically crashes the
|
||||||
|
* process, unless it has an unhandled exception handler.
|
||||||
|
*
|
||||||
|
* See {@link ActivityThread#throwRemoteServiceException}.
|
||||||
|
*
|
||||||
|
* @param message exception message
|
||||||
|
* @param exceptionTypeId ID defined in {@link android.app.RemoteServiceException} or one
|
||||||
|
* of its subclasses.
|
||||||
|
*/
|
||||||
|
@GuardedBy("mService")
|
||||||
|
void scheduleCrashLocked(String message, int exceptionTypeId) {
|
||||||
// Checking killedbyAm should keep it from showing the crash dialog if the process
|
// Checking killedbyAm should keep it from showing the crash dialog if the process
|
||||||
// was already dead for a good / normal reason.
|
// was already dead for a good / normal reason.
|
||||||
if (!mKilledByAm) {
|
if (!mKilledByAm) {
|
||||||
@@ -959,7 +975,7 @@ class ProcessRecord implements WindowProcessListener {
|
|||||||
}
|
}
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mThread.scheduleCrash(message);
|
mThread.scheduleCrash(message, exceptionTypeId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// If it's already dead our work is done. If it's wedged just kill it.
|
// If it's already dead our work is done. If it's wedged just kill it.
|
||||||
// We won't get the crash dialog or the error reporting.
|
// We won't get the crash dialog or the error reporting.
|
||||||
|
|||||||
Reference in New Issue
Block a user