summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rwxr-xr-xapi/current.txt6
-rw-r--r--api/system-current.txt3
-rw-r--r--cmds/statsd/src/atoms.proto26
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp3
-rw-r--r--config/hiddenapi-light-greylist.txt263
-rw-r--r--config/hiddenapi-vendor-list.txt8
-rw-r--r--core/java/android/app/ActivityManagerInternal.java30
-rw-r--r--core/java/android/app/FragmentTransition.java5
-rw-r--r--core/java/android/app/NotificationChannel.java5
-rw-r--r--core/java/android/content/ContentProvider.java42
-rw-r--r--core/java/android/hardware/location/ContextHubClient.java15
-rw-r--r--core/java/android/os/UserManager.java4
-rw-r--r--core/java/android/os/storage/StorageManager.java6
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java6
-rw-r--r--core/java/android/transition/TransitionManager.java1
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java40
-rw-r--r--core/java/android/webkit/WebViewClient.java2
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodDebug.java158
-rw-r--r--core/java/com/android/internal/inputmethod/StartInputReason.java92
-rw-r--r--core/java/com/android/internal/inputmethod/UnbindReason.java69
-rw-r--r--core/java/com/android/internal/os/KernelWakelockReader.java2
-rw-r--r--core/java/com/android/internal/view/IInputMethodClient.aidl1
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl2
-rw-r--r--core/java/com/android/internal/view/InputMethodClient.java169
-rw-r--r--libs/hwui/hwui/MinikinSkia.cpp2
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java7
-rw-r--r--media/jni/Android.bp1
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/AgingHelper.java2
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java8
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java9
-rw-r--r--services/core/java/com/android/server/VibratorService.java63
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityDisplay.java46
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2015
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java18
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java180
-rw-r--r--services/core/java/com/android/server/am/ActivityTaskManagerService.java69
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java16
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java4
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java1764
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java62
-rw-r--r--services/core/java/com/android/server/am/WindowProcessController.java30
-rw-r--r--services/core/java/com/android/server/am/WindowProcessListener.java12
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java77
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java69
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientBroker.java17
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientManager.java19
-rw-r--r--services/core/java/com/android/server/location/ContextHubService.java6
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java26
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java35
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java72
-rw-r--r--services/core/java/com/android/server/power/batterysaver/BatterySaverController.java6
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java109
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java (renamed from services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java)24
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java56
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java57
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java42
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java56
-rw-r--r--services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java141
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java36
-rw-r--r--services/usage/java/com/android/server/usage/AppIdleHistory.java19
-rw-r--r--services/usage/java/com/android/server/usage/AppStandbyController.java8
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java2
-rw-r--r--telephony/java/android/telephony/RcsManager.java52
-rw-r--r--telephony/java/android/telephony/ServiceState.java15
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java37
-rw-r--r--telephony/java/android/telephony/ims/feature/MmTelFeature.java53
-rw-r--r--telephony/java/com/android/internal/telephony/IRcs.aidl21
79 files changed, 3594 insertions, 2775 deletions
diff --git a/Android.bp b/Android.bp
index 52e2508099ba..d94bd8439349 100644
--- a/Android.bp
+++ b/Android.bp
@@ -560,6 +560,7 @@ java_defaults {
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
+ "telephony/java/com/android/internal/telephony/IRcs.aidl",
"telephony/java/com/android/internal/telephony/ISms.aidl",
"telephony/java/com/android/internal/telephony/ISub.aidl",
"telephony/java/com/android/internal/telephony/IAns.aidl",
diff --git a/api/current.txt b/api/current.txt
index df24fc5c7546..21bab7cf5d1e 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -5676,6 +5676,7 @@ package android.app {
method public java.lang.CharSequence getName();
method public android.net.Uri getSound();
method public long[] getVibrationPattern();
+ method public boolean hasUserSetImportance();
method public void setBypassDnd(boolean);
method public void setDescription(java.lang.String);
method public void setGroup(java.lang.String);
@@ -9168,6 +9169,7 @@ package android.content {
method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
method public android.net.Uri canonicalize(android.net.Uri);
+ method public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public final java.lang.String getCallingPackage();
@@ -9195,6 +9197,7 @@ package android.content {
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
+ method public final void restoreCallingIdentity(android.content.ContentProvider.CallingIdentity);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
method protected final void setWritePermission(java.lang.String);
@@ -9203,6 +9206,9 @@ package android.content {
method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
+ public final class ContentProvider.CallingIdentity {
+ }
+
public static abstract interface ContentProvider.PipeDataWriter<T> {
method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 782c5a5e604e..26036ea9c281 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6390,7 +6390,8 @@ package android.telephony.ims.feature {
}
public static class MmTelFeature.MmTelCapabilities {
- ctor public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+ ctor public MmTelFeature.MmTelCapabilities();
+ ctor public deprecated MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
ctor public MmTelFeature.MmTelCapabilities(int);
method public final void addCapabilities(int);
method public final boolean isCapable(int);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 10ad1208d20d..c2fed66eea41 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -143,6 +143,7 @@ message Atom {
BatteryCausedShutdown battery_caused_shutdown = 93;
PhoneServiceStateChanged phone_service_state_changed = 94;
PhoneStateChanged phone_state_changed = 95;
+ UserRestrictionChanged user_restriction_changed = 96;
}
// Pulled events will start at field 10000.
@@ -183,7 +184,6 @@ message Atom {
DiskIo disk_io = 10032;
PowerProfile power_profile = 10033;
ProcStats proc_stats_pkg_proc = 10034;
- ProcessCpuTime process_cpu_time = 10035;
NativeProcessMemoryState native_process_memory_state = 10036;
}
@@ -3035,17 +3035,15 @@ message PowerProfile {
}
/**
- * Pulls process user time and system time. Puller takes a snapshot of all pids
- * in the system and returns cpu stats for those that are working at the time.
- * Dead pids will be dropped. Kernel processes are excluded.
- * Min cool-down is 5 sec.
+ * Logs when a user restriction was added or removed.
+ *
+ * Logged from:
+ * frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
*/
-message ProcessCpuTime {
- optional int32 uid = 1 [(is_uid) = true];
-
- optional string process_name = 2;
- // Process cpu time in user space, cumulative from boot/process start
- optional int64 user_time_millis = 3;
- // Process cpu time in system space, cumulative from boot/process start
- optional int64 system_time_millis = 4;
-}
+message UserRestrictionChanged {
+ // The raw string of the user restriction as defined in UserManager.
+ // Allowed values are defined in UserRestrictionsUtils#USER_RESTRICTIONS.
+ optional string restriction = 1;
+ // Whether the restriction is enabled or disabled.
+ optional bool enabled = 2;
+} \ No newline at end of file
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8871d4d054c5..1a9ba8a8de17 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -229,9 +229,6 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
// PowerProfile constants for power model calculations.
{android::util::POWER_PROFILE,
{{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
- // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
- {android::util::PROCESS_CPU_TIME,
- {{}, {}, 5 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 857c39045085..bbc3f35aa05a 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1383,62 +1383,6 @@ Landroid/service/wallpaper/IWallpaperEngine;->dispatchWallpaperCommand(Ljava/lan
Landroid/service/wallpaper/IWallpaperEngine;->setVisibility(Z)V
Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
-Landroid/system/Int32Ref;->value:I
-Landroid/system/OsConstants;-><init>()V
-Landroid/system/OsConstants;->AF_NETLINK:I
-Landroid/system/OsConstants;->AF_PACKET:I
-Landroid/system/OsConstants;->ARPHRD_ETHER:I
-Landroid/system/OsConstants;->ARPHRD_LOOPBACK:I
-Landroid/system/OsConstants;->CAP_TO_INDEX(I)I
-Landroid/system/OsConstants;->CAP_TO_MASK(I)I
-Landroid/system/OsConstants;->ENONET:I
-Landroid/system/OsConstants;->ETH_P_ALL:I
-Landroid/system/OsConstants;->ETH_P_ARP:I
-Landroid/system/OsConstants;->ETH_P_IP:I
-Landroid/system/OsConstants;->ETH_P_IPV6:I
-Landroid/system/OsConstants;->EUSERS:I
-Landroid/system/OsConstants;->ICMP6_ECHO_REPLY:I
-Landroid/system/OsConstants;->ICMP6_ECHO_REQUEST:I
-Landroid/system/OsConstants;->ICMP_ECHO:I
-Landroid/system/OsConstants;->ICMP_ECHOREPLY:I
-Landroid/system/OsConstants;->initConstants()V
-Landroid/system/OsConstants;->IP_MULTICAST_ALL:I
-Landroid/system/OsConstants;->IP_RECVTOS:I
-Landroid/system/OsConstants;->MAP_POPULATE:I
-Landroid/system/OsConstants;->NETLINK_NETFILTER:I
-Landroid/system/OsConstants;->NETLINK_ROUTE:I
-Landroid/system/OsConstants;->O_DIRECT:I
-Landroid/system/OsConstants;->placeholder()I
-Landroid/system/OsConstants;->PR_CAP_AMBIENT:I
-Landroid/system/OsConstants;->PR_CAP_AMBIENT_RAISE:I
-Landroid/system/OsConstants;->RLIMIT_NOFILE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_IFADDR:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_MROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_ROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_RULE:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_IFADDR:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_IFINFO:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_MROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_PREFIX:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_ROUTE:I
-Landroid/system/OsConstants;->RTMGRP_LINK:I
-Landroid/system/OsConstants;->RTMGRP_NEIGH:I
-Landroid/system/OsConstants;->RTMGRP_NOTIFY:I
-Landroid/system/OsConstants;->RTMGRP_TC:I
-Landroid/system/OsConstants;->SO_DOMAIN:I
-Landroid/system/OsConstants;->SO_PROTOCOL:I
-Landroid/system/OsConstants;->SPLICE_F_MORE:I
-Landroid/system/OsConstants;->SPLICE_F_MOVE:I
-Landroid/system/OsConstants;->SPLICE_F_NONBLOCK:I
-Landroid/system/OsConstants;->TIOCOUTQ:I
-Landroid/system/OsConstants;->UDP_ENCAP:I
-Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP:I
-Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP_NON_IKE:I
-Landroid/system/OsConstants;->UNIX_PATH_MAX:I
-Landroid/system/OsConstants;->XATTR_CREATE:I
-Landroid/system/OsConstants;->XATTR_REPLACE:I
-Landroid/system/OsConstants;->_LINUX_CAPABILITY_VERSION_3:I
-Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
Landroid/util/Singleton;-><init>()V
@@ -2339,93 +2283,6 @@ Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/andr
Lcom/google/android/mms/util/PduCache;->purgeAll()V
Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu;
Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
-Ldalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/io/File;Ljava/lang/String;Ljava/lang/ClassLoader;Z)V
-Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
-Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;Z)V
-Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
-Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
-Ldalvik/system/BlockGuard$BlockGuardPolicyException;-><init>(IILjava/lang/String;)V
-Ldalvik/system/BlockGuard$BlockGuardPolicyException;->mMessage:Ljava/lang/String;
-Ldalvik/system/BlockGuard$BlockGuardPolicyException;->mPolicyState:I
-Ldalvik/system/BlockGuard$BlockGuardPolicyException;->mPolicyViolated:I
-Ldalvik/system/BlockGuard$Policy;->onNetwork()V
-Ldalvik/system/BlockGuard$Policy;->onReadFromDisk()V
-Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy;
-Ldalvik/system/BlockGuard;->LAX_POLICY:Ldalvik/system/BlockGuard$Policy;
-Ldalvik/system/BlockGuard;->setThreadPolicy(Ldalvik/system/BlockGuard$Policy;)V
-Ldalvik/system/BlockGuard;->threadPolicy:Ljava/lang/ThreadLocal;
-Ldalvik/system/CloseGuard$DefaultReporter;-><init>()V
-Ldalvik/system/CloseGuard$Reporter;->report(Ljava/lang/String;Ljava/lang/Throwable;)V
-Ldalvik/system/CloseGuard;-><init>()V
-Ldalvik/system/CloseGuard;->close()V
-Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard;
-Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V
-Ldalvik/system/CloseGuard;->setEnabled(Z)V
-Ldalvik/system/CloseGuard;->setReporter(Ldalvik/system/CloseGuard$Reporter;)V
-Ldalvik/system/CloseGuard;->warnIfOpen()V
-Ldalvik/system/DexFile$DFEnum;->mNameList:[Ljava/lang/String;
-Ldalvik/system/DexFile;->getClassNameList(Ljava/lang/Object;)[Ljava/lang/String;
-Ldalvik/system/DexFile;->isBackedByOatFile()Z
-Ldalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
-Ldalvik/system/DexFile;->loadDex(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
-Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object;
-Ldalvik/system/DexFile;->mFileName:Ljava/lang/String;
-Ldalvik/system/DexFile;->mInternalCookie:Ljava/lang/Object;
-Ldalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
-Ldalvik/system/DexFile;->openDexFileNative(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
-Ldalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;Ljava/io/File;)V
-Ldalvik/system/DexPathList$Element;-><init>(Ljava/io/File;ZLjava/io/File;Ldalvik/system/DexFile;)V
-Ldalvik/system/DexPathList$Element;->dexFile:Ldalvik/system/DexFile;
-Ldalvik/system/DexPathList$Element;->path:Ljava/io/File;
-Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
-Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
-Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
-Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
-Ldalvik/system/DexPathList;->addNativePath(Ljava/util/Collection;)V
-Ldalvik/system/DexPathList;->definingContext:Ljava/lang/ClassLoader;
-Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->dexElementsSuppressedExceptions:[Ljava/io/IOException;
-Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
-Ldalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->makeInMemoryDexElements([Ljava/nio/ByteBuffer;Ljava/util/List;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;)[Ldalvik/system/DexPathList$NativeLibraryElement;
-Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->nativeLibraryDirectories:Ljava/util/List;
-Ldalvik/system/DexPathList;->nativeLibraryPathElements:[Ldalvik/system/DexPathList$NativeLibraryElement;
-Ldalvik/system/DexPathList;->splitPaths(Ljava/lang/String;Z)Ljava/util/List;
-Ldalvik/system/DexPathList;->systemNativeLibraryDirectories:Ljava/util/List;
-Ldalvik/system/SocketTagger;->get()Ldalvik/system/SocketTagger;
-Ldalvik/system/SocketTagger;->tag(Ljava/net/Socket;)V
-Ldalvik/system/SocketTagger;->untag(Ljava/net/Socket;)V
-Ldalvik/system/VMDebug;->allowHiddenApiReflectionFrom(Ljava/lang/Class;)V
-Ldalvik/system/VMDebug;->dumpReferenceTables()V
-Ldalvik/system/VMDebug;->isDebuggerConnected()Z
-Ldalvik/system/VMRuntime;->addressOf(Ljava/lang/Object;)J
-Ldalvik/system/VMRuntime;->clearGrowthLimit()V
-Ldalvik/system/VMRuntime;->gcSoftReferences()V
-Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
-Ldalvik/system/VMRuntime;->getExternalBytesAllocated()J
-Ldalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;
-Ldalvik/system/VMRuntime;->getMinimumHeapSize()J
-Ldalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime;
-Ldalvik/system/VMRuntime;->is64Bit()Z
-Ldalvik/system/VMRuntime;->is64BitAbi(Ljava/lang/String;)Z
-Ldalvik/system/VMRuntime;->newNonMovableArray(Ljava/lang/Class;I)Ljava/lang/Object;
-Ldalvik/system/VMRuntime;->registerNativeAllocation(I)V
-Ldalvik/system/VMRuntime;->registerNativeFree(I)V
-Ldalvik/system/VMRuntime;->runFinalization(J)V
-Ldalvik/system/VMRuntime;->runFinalizationSync()V
-Ldalvik/system/VMRuntime;->setMinimumHeapSize(J)J
-Ldalvik/system/VMRuntime;->setTargetHeapUtilization(F)F
-Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
-Ldalvik/system/VMRuntime;->trackExternalAllocation(J)Z
-Ldalvik/system/VMRuntime;->trackExternalFree(J)V
-Ldalvik/system/VMRuntime;->vmInstructionSet()Ljava/lang/String;
-Ldalvik/system/VMRuntime;->vmLibrary()Ljava/lang/String;
-Ldalvik/system/VMStack;->fillStackTraceElements(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I
-Ldalvik/system/VMStack;->getCallingClassLoader()Ljava/lang/ClassLoader;
-Ldalvik/system/VMStack;->getStackClass2()Ljava/lang/Class;
-Ldalvik/system/VMStack;->getThreadStackTrace(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;
Ljava/io/Console;->encoding()Ljava/lang/String;
Ljava/io/File;->filePath:Ljava/nio/file/Path;
Ljava/io/File;->fs:Ljava/io/FileSystem;
@@ -2501,18 +2358,6 @@ Ljava/lang/Class;->name:Ljava/lang/String;
Ljava/lang/Class;->objectSize:I
Ljava/lang/Class;->status:I
Ljava/lang/ClassLoader;->parent:Ljava/lang/ClassLoader;
-Ljava/lang/Daemons$Daemon;->isRunning()Z
-Ljava/lang/Daemons$Daemon;->start()V
-Ljava/lang/Daemons$Daemon;->stop()V
-Ljava/lang/Daemons$Daemon;->thread:Ljava/lang/Thread;
-Ljava/lang/Daemons$FinalizerDaemon;->finalizingObject:Ljava/lang/Object;
-Ljava/lang/Daemons$FinalizerDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;
-Ljava/lang/Daemons$FinalizerWatchdogDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon;
-Ljava/lang/Daemons$ReferenceQueueDaemon;->INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;
-Ljava/lang/Daemons;->MAX_FINALIZE_NANOS:J
-Ljava/lang/Daemons;->requestHeapTrim()V
-Ljava/lang/Daemons;->start()V
-Ljava/lang/Daemons;->stop()V
Ljava/lang/Double;->value:D
Ljava/lang/Enum;->getSharedConstants(Ljava/lang/Class;)[Ljava/lang/Enum;
Ljava/lang/Enum;->name:Ljava/lang/String;
@@ -2522,11 +2367,6 @@ Ljava/lang/Integer;->value:I
Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V
Ljava/lang/Long;->value:J
Ljava/lang/Object;->identityHashCode(Ljava/lang/Object;)I
-Ljava/lang/ref/FinalizerReference;->add(Ljava/lang/Object;)V
-Ljava/lang/ref/FinalizerReference;->head:Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/FinalizerReference;->next:Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/FinalizerReference;->queue:Ljava/lang/ref/ReferenceQueue;
-Ljava/lang/ref/FinalizerReference;->remove(Ljava/lang/ref/FinalizerReference;)V
Ljava/lang/ref/Reference;->getReferent()Ljava/lang/Object;
Ljava/lang/ref/Reference;->referent:Ljava/lang/Object;
Ljava/lang/ref/ReferenceQueue;->add(Ljava/lang/ref/Reference;)V
@@ -2669,12 +2509,6 @@ Ljava/nio/CharBuffer;->toString(II)Ljava/lang/String;
Ljava/nio/charset/Charset;->defaultCharset:Ljava/nio/charset/Charset;
Ljava/nio/charset/CharsetEncoder;->canEncode(Ljava/nio/CharBuffer;)Z
Ljava/nio/DirectByteBuffer;-><init>(JI)V
-Ljava/nio/NIOAccess;->getBaseArray(Ljava/nio/Buffer;)Ljava/lang/Object;
-Ljava/nio/NIOAccess;->getBaseArrayOffset(Ljava/nio/Buffer;)I
-Ljava/nio/NIOAccess;->getBasePointer(Ljava/nio/Buffer;)J
-Ljava/nio/NioUtils;->freeDirectBuffer(Ljava/nio/ByteBuffer;)V
-Ljava/nio/NioUtils;->unsafeArray(Ljava/nio/ByteBuffer;)[B
-Ljava/nio/NioUtils;->unsafeArrayOffset(Ljava/nio/ByteBuffer;)I
Ljava/security/KeyPairGenerator;->getInstance(Lsun/security/jca/GetInstance$Instance;Ljava/lang/String;)Ljava/security/KeyPairGenerator;
Ljava/security/KeyStore;->keyStoreSpi:Ljava/security/KeyStoreSpi;
Ljava/security/Signature;->getInstance(Lsun/security/jca/GetInstance$Instance;Ljava/lang/String;)Ljava/security/Signature;
@@ -2790,9 +2624,6 @@ Ljava/util/zip/ZipOutputStream;->written:J
Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory;
Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket;
Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
-Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale;
-Llibcore/util/BasicLruCache;->map:Ljava/util/LinkedHashMap;
-Llibcore/util/ZoneInfo;->mTransitions:[J
Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
Lorg/ccil/cowan/tagsoup/ElementType;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
@@ -2811,100 +2642,6 @@ Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/Schema;->theRoot:Lorg/ccil/cowan/tagsoup/ElementType;
Lorg/ccil/cowan/tagsoup/Schema;->theURI:Ljava/lang/String;
-Lorg/json/JSONArray;->values:Ljava/util/List;
-Lorg/json/JSONArray;->writeTo(Lorg/json/JSONStringer;)V
-Lorg/json/JSONObject;->append(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
-Lorg/json/JSONObject;->checkName(Ljava/lang/String;)Ljava/lang/String;
-Lorg/json/JSONObject;->keySet()Ljava/util/Set;
-Lorg/json/JSONObject;->nameValuePairs:Ljava/util/LinkedHashMap;
-Lorg/json/JSONObject;->NEGATIVE_ZERO:Ljava/lang/Double;
-Lorg/json/JSONObject;->writeTo(Lorg/json/JSONStringer;)V
-Lorg/json/JSONStringer;-><init>(I)V
-Lorg/json/JSONStringer;->beforeKey()V
-Lorg/json/JSONStringer;->beforeValue()V
-Lorg/json/JSONStringer;->close(Lorg/json/JSONStringer$Scope;Lorg/json/JSONStringer$Scope;Ljava/lang/String;)Lorg/json/JSONStringer;
-Lorg/json/JSONStringer;->indent:Ljava/lang/String;
-Lorg/json/JSONStringer;->newline()V
-Lorg/json/JSONStringer;->open(Lorg/json/JSONStringer$Scope;Ljava/lang/String;)Lorg/json/JSONStringer;
-Lorg/json/JSONStringer;->out:Ljava/lang/StringBuilder;
-Lorg/json/JSONStringer;->peek()Lorg/json/JSONStringer$Scope;
-Lorg/json/JSONStringer;->replaceTop(Lorg/json/JSONStringer$Scope;)V
-Lorg/json/JSONStringer;->stack:Ljava/util/List;
-Lorg/json/JSONStringer;->string(Ljava/lang/String;)V
-Lorg/json/JSONTokener;->in:Ljava/lang/String;
-Lorg/json/JSONTokener;->nextCleanInternal()I
-Lorg/json/JSONTokener;->nextToInternal(Ljava/lang/String;)Ljava/lang/String;
-Lorg/json/JSONTokener;->pos:I
-Lorg/json/JSONTokener;->readArray()Lorg/json/JSONArray;
-Lorg/json/JSONTokener;->readEscapeCharacter()C
-Lorg/json/JSONTokener;->readLiteral()Ljava/lang/Object;
-Lorg/json/JSONTokener;->readObject()Lorg/json/JSONObject;
-Lorg/json/JSONTokener;->skipToEndOfLine()V
-Lorg/w3c/dom/ls/LSSerializerFilter;->getWhatToShow()I
-Lorg/w3c/dom/traversal/NodeFilter;->acceptNode(Lorg/w3c/dom/Node;)S
-Lorg/w3c/dom/traversal/NodeIterator;->detach()V
-Lorg/w3c/dom/traversal/NodeIterator;->nextNode()Lorg/w3c/dom/Node;
-Lorg/xml/sax/ext/Attributes2Impl;->declared:[Z
-Lorg/xml/sax/ext/Attributes2Impl;->specified:[Z
-Lorg/xml/sax/ext/Locator2Impl;->encoding:Ljava/lang/String;
-Lorg/xml/sax/ext/Locator2Impl;->version:Ljava/lang/String;
-Lorg/xml/sax/helpers/AttributesImpl;->badIndex(I)V
-Lorg/xml/sax/helpers/AttributesImpl;->data:[Ljava/lang/String;
-Lorg/xml/sax/helpers/AttributesImpl;->ensureCapacity(I)V
-Lorg/xml/sax/helpers/AttributesImpl;->length:I
-Lorg/xml/sax/helpers/LocatorImpl;->columnNumber:I
-Lorg/xml/sax/helpers/LocatorImpl;->lineNumber:I
-Lorg/xml/sax/helpers/LocatorImpl;->publicId:Ljava/lang/String;
-Lorg/xml/sax/helpers/LocatorImpl;->systemId:Ljava/lang/String;
-Lorg/xml/sax/helpers/NamespaceSupport;->contextPos:I
-Lorg/xml/sax/helpers/NamespaceSupport;->contexts:[Lorg/xml/sax/helpers/NamespaceSupport$Context;
-Lorg/xml/sax/helpers/NamespaceSupport;->currentContext:Lorg/xml/sax/helpers/NamespaceSupport$Context;
-Lorg/xml/sax/helpers/NamespaceSupport;->EMPTY_ENUMERATION:Ljava/util/Enumeration;
-Lorg/xml/sax/helpers/NamespaceSupport;->namespaceDeclUris:Z
-Lorg/xml/sax/helpers/ParserAdapter;->attAdapter:Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;
-Lorg/xml/sax/helpers/ParserAdapter;->atts:Lorg/xml/sax/helpers/AttributesImpl;
-Lorg/xml/sax/helpers/ParserAdapter;->checkNotParsing(Ljava/lang/String;Ljava/lang/String;)V
-Lorg/xml/sax/helpers/ParserAdapter;->contentHandler:Lorg/xml/sax/ContentHandler;
-Lorg/xml/sax/helpers/ParserAdapter;->dtdHandler:Lorg/xml/sax/DTDHandler;
-Lorg/xml/sax/helpers/ParserAdapter;->entityResolver:Lorg/xml/sax/EntityResolver;
-Lorg/xml/sax/helpers/ParserAdapter;->errorHandler:Lorg/xml/sax/ErrorHandler;
-Lorg/xml/sax/helpers/ParserAdapter;->locator:Lorg/xml/sax/Locator;
-Lorg/xml/sax/helpers/ParserAdapter;->makeException(Ljava/lang/String;)Lorg/xml/sax/SAXParseException;
-Lorg/xml/sax/helpers/ParserAdapter;->nameParts:[Ljava/lang/String;
-Lorg/xml/sax/helpers/ParserAdapter;->namespaces:Z
-Lorg/xml/sax/helpers/ParserAdapter;->nsSupport:Lorg/xml/sax/helpers/NamespaceSupport;
-Lorg/xml/sax/helpers/ParserAdapter;->parser:Lorg/xml/sax/Parser;
-Lorg/xml/sax/helpers/ParserAdapter;->parsing:Z
-Lorg/xml/sax/helpers/ParserAdapter;->prefixes:Z
-Lorg/xml/sax/helpers/ParserAdapter;->processName(Ljava/lang/String;ZZ)[Ljava/lang/String;
-Lorg/xml/sax/helpers/ParserAdapter;->reportError(Ljava/lang/String;)V
-Lorg/xml/sax/helpers/ParserAdapter;->setup(Lorg/xml/sax/Parser;)V
-Lorg/xml/sax/helpers/ParserAdapter;->setupParser()V
-Lorg/xml/sax/helpers/ParserAdapter;->uris:Z
-Lorg/xml/sax/helpers/XMLFilterImpl;->contentHandler:Lorg/xml/sax/ContentHandler;
-Lorg/xml/sax/helpers/XMLFilterImpl;->dtdHandler:Lorg/xml/sax/DTDHandler;
-Lorg/xml/sax/helpers/XMLFilterImpl;->entityResolver:Lorg/xml/sax/EntityResolver;
-Lorg/xml/sax/helpers/XMLFilterImpl;->errorHandler:Lorg/xml/sax/ErrorHandler;
-Lorg/xml/sax/helpers/XMLFilterImpl;->locator:Lorg/xml/sax/Locator;
-Lorg/xml/sax/helpers/XMLFilterImpl;->parent:Lorg/xml/sax/XMLReader;
-Lorg/xml/sax/helpers/XMLFilterImpl;->setupParse()V
-Lorg/xml/sax/helpers/XMLReaderAdapter;->documentHandler:Lorg/xml/sax/DocumentHandler;
-Lorg/xml/sax/helpers/XMLReaderAdapter;->qAtts:Lorg/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter;
-Lorg/xml/sax/helpers/XMLReaderAdapter;->setup(Lorg/xml/sax/XMLReader;)V
-Lorg/xml/sax/helpers/XMLReaderAdapter;->setupXMLReader()V
-Lorg/xml/sax/helpers/XMLReaderAdapter;->xmlReader:Lorg/xml/sax/XMLReader;
-Lorg/xml/sax/helpers/XMLReaderFactory;->loadClass(Ljava/lang/ClassLoader;Ljava/lang/String;)Lorg/xml/sax/XMLReader;
-Lorg/xml/sax/InputSource;->byteStream:Ljava/io/InputStream;
-Lorg/xml/sax/InputSource;->characterStream:Ljava/io/Reader;
-Lorg/xml/sax/InputSource;->encoding:Ljava/lang/String;
-Lorg/xml/sax/InputSource;->publicId:Ljava/lang/String;
-Lorg/xml/sax/InputSource;->systemId:Ljava/lang/String;
-Lorg/xml/sax/SAXException;->exception:Ljava/lang/Exception;
-Lorg/xml/sax/SAXParseException;->columnNumber:I
-Lorg/xml/sax/SAXParseException;->init(Ljava/lang/String;Ljava/lang/String;II)V
-Lorg/xml/sax/SAXParseException;->lineNumber:I
-Lorg/xml/sax/SAXParseException;->publicId:Ljava/lang/String;
-Lorg/xml/sax/SAXParseException;->systemId:Ljava/lang/String;
Lsun/misc/Cleaner;->clean()V
Lsun/misc/Unsafe;->addressSize()I
Lsun/misc/Unsafe;->allocateInstance(Ljava/lang/Class;)Ljava/lang/Object;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 45e38cf95de0..e5e64d34f721 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -122,14 +122,6 @@ Landroid/os/UserHandle;->isSameApp(II)Z
Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
Landroid/os/UserManager;->isAdminUser()Z
Landroid/R$styleable;->CheckBoxPreference:[I
-Landroid/system/NetlinkSocketAddress;-><init>(II)V
-Landroid/system/Os;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V
-Landroid/system/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V
-Landroid/system/Os;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/SocketAddress;)I
-Landroid/system/Os;->setsockoptIfreq(Ljava/io/FileDescriptor;IILjava/lang/String;)V
-Landroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
-Landroid/system/PacketSocketAddress;-><init>(I[B)V
-Landroid/system/PacketSocketAddress;-><init>(SI)V
Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
Landroid/telephony/ims/compat/ImsService;-><init>()V
Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index d00650d40d8f..069effd3ef19 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -250,4 +250,34 @@ public abstract class ActivityManagerInternal {
public abstract boolean inputDispatchingTimedOut(Object proc, String activityShortComponentName,
ApplicationInfo aInfo, String parentShortComponentName, Object parentProc,
boolean aboveSystem, String reason);
+
+ /**
+ * Sends {@link android.content.Intent#ACTION_CONFIGURATION_CHANGED} with all the appropriate
+ * flags.
+ */
+ public abstract void broadcastGlobalConfigurationChanged(int changes, boolean initLocale);
+
+ /**
+ * Sends {@link android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS} with all the appropriate
+ * flags.
+ */
+ public abstract void broadcastCloseSystemDialogs(String reason);
+
+ /**
+ * Kills all background processes, except those matching any of the specified properties.
+ *
+ * @param minTargetSdk the target SDK version at or above which to preserve processes,
+ * or {@code -1} to ignore the target SDK
+ * @param maxProcState the process state at or below which to preserve processes,
+ * or {@code -1} to ignore the process state
+ */
+ public abstract void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState);
+
+ /** Starts a given process. */
+ public abstract void startProcess(String processName, ApplicationInfo info,
+ boolean knownToBeDead, String hostingType, ComponentName hostingName);
+
+ /** Starts up the starting activity process for debugging if needed. */
+ public abstract void setDebugFlagsForStartingActivity(ActivityInfo aInfo, int startFlags,
+ ProfilerInfo profilerInfo);
}
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index ceb828b64add..0e428ae164a4 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -1013,6 +1013,11 @@ class FragmentTransition {
replaceTargets(sharedElementTransition, sharedElementsIn, null);
}
}
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ transition.removeListener(this);
+ }
});
}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 848def63177e..9f93e1765da3 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -603,9 +603,10 @@ public final class NotificationChannel implements Parcelable {
}
/**
- * @hide
+ * Returns whether the user has chosen the importance of this channel, either to affirm the
+ * initial selection from the app, or changed it to be higher or lower.
*/
- public boolean isImportanceLocked() {
+ public boolean hasUserSetImportance() {
return (mUserLockedFields & USER_LOCKED_IMPORTANCE) != 0;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 2a03787f134c..145c92731458 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -822,6 +822,48 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/**
+ * Opaque token representing the identity of an incoming IPC.
+ */
+ public final class CallingIdentity {
+ /** {@hide} */
+ public final long binderToken;
+ /** {@hide} */
+ public final String callingPackage;
+
+ /** {@hide} */
+ public CallingIdentity(long binderToken, String callingPackage) {
+ this.binderToken = binderToken;
+ this.callingPackage = callingPackage;
+ }
+ }
+
+ /**
+ * Reset the identity of the incoming IPC on the current thread.
+ * <p>
+ * Internally this calls {@link Binder#clearCallingIdentity()} and also
+ * clears any value stored in {@link #getCallingPackage()}.
+ *
+ * @return Returns an opaque token that can be used to restore the original
+ * calling identity by passing it to
+ * {@link #restoreCallingIdentity}.
+ */
+ public final @NonNull CallingIdentity clearCallingIdentity() {
+ return new CallingIdentity(Binder.clearCallingIdentity(), setCallingPackage(null));
+ }
+
+ /**
+ * Restore the identity of the incoming IPC on the current thread back to a
+ * previously identity that was returned by {@link #clearCallingIdentity}.
+ * <p>
+ * Internally this calls {@link Binder#restoreCallingIdentity(long)} and
+ * also restores any value stored in {@link #getCallingPackage()}.
+ */
+ public final void restoreCallingIdentity(@NonNull CallingIdentity identity) {
+ Binder.restoreCallingIdentity(identity.binderToken);
+ mCallingPackage.set(identity.callingPackage);
+ }
+
+ /**
* Change the authorities of the ContentProvider.
* This is normally set for you from its manifest information when the provider is first
* created.
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 6609b76faac1..5de89e3422ab 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -105,12 +105,15 @@ public class ContextHubClient implements Closeable {
*
* This method should be used if the caller wants to receive notifications even after the
* process exits. The client must have an open connection with the Context Hub Service (i.e. it
- * cannot have been closed through the {@link #close()} method). If registered successfully,
- * intents will be delivered regarding events for the specified nanoapp from the attached
- * Context Hub. Any unicast messages for this client will also be delivered. The intent will
- * have an extra {@link #EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which will
- * contain the type of the event. See {@link ContextHubManager.Event} for description of each
- * event type.
+ * cannot have been closed through the {@link #close()} method). Only one PendingIntent can be
+ * registered at a time for a single ContextHubClient. If registered successfully, intents will
+ * be delivered regarding events for the specified nanoapp from the attached Context Hub. Any
+ * unicast messages for this client will also be delivered. The intent will have an extra
+ * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
+ * describes the Context Hub the intent event was for. The intent will also have an extra
+ * {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
+ * will contain the type of the event. See {@link ContextHubManager.Event} for description of
+ * each event type, along with event-specific extra fields.
*
* When the intent is received, this client can be recreated through
* {@link ContextHubManager.createClient(PendingIntent, ContextHubInfo,
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0d5d54704c4f..00b989e03c61 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -272,6 +272,10 @@ public class UserManager {
*
* Specifies if all users on the device are disallowed from enabling the
* "Unknown Sources" setting, that allows installation of apps from unknown sources.
+ *
+ * This restriction can be enabled by the profile owner, in which case all accounts and
+ * profiles will be affected.
+ *
* The default value is <code>false</code>.
*
* <p>Key for user restrictions.
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 50ca4abd6713..df771df5de0d 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1538,6 +1538,9 @@ public class StorageManager {
* @hide
*/
public File translateAppToSystem(File file, String packageName) {
+ // We can only translate absolute paths
+ if (!file.isAbsolute()) return file;
+
try {
return new File(mStorageManager.translateAppToSystem(file.getAbsolutePath(),
packageName, mContext.getUserId()));
@@ -1553,6 +1556,9 @@ public class StorageManager {
* @hide
*/
public File translateSystemToApp(File file, String packageName) {
+ // We can only translate absolute paths
+ if (!file.isAbsolute()) return file;
+
try {
return new File(mStorageManager.translateSystemToApp(file.getAbsolutePath(),
packageName, mContext.getUserId()));
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index d7fe15d0e925..b8e03876a836 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -737,7 +737,8 @@ public abstract class NotificationListenerService extends Service {
* <p>This method will throw a security exception if you don't have access to notifications
* for the given user.</p>
* <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
- * device} in order to use this method.
+ * device} or be the {@link NotificationAssistantService notification assistant} in order to
+ * use this method.
*
* @param pkg The package to retrieve channels for.
*/
@@ -760,7 +761,8 @@ public abstract class NotificationListenerService extends Service {
* <p>This method will throw a security exception if you don't have access to notifications
* for the given user.</p>
* <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
- * device} in order to use this method.
+ * device} or be the {@link NotificationAssistantService notification assistant} in order to
+ * use this method.
*
* @param pkg The package to retrieve channel groups for.
*/
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 4608e205ec7c..0e5252e21a64 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -315,6 +315,7 @@ public class TransitionManager {
ArrayList<Transition> currentTransitions =
runningTransitions.get(mSceneRoot);
currentTransitions.remove(transition);
+ transition.removeListener(this);
}
});
mTransition.captureValues(mSceneRoot, false);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index a401c6def23a..e370e1175de5 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -59,7 +59,10 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.autofill.AutofillManager;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
+import com.android.internal.inputmethod.StartInputReason;
+import com.android.internal.inputmethod.UnbindReason;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputConnectionWrapper;
import com.android.internal.view.IInputContext;
@@ -67,7 +70,6 @@ import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
-import com.android.internal.view.InputMethodClient;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -540,17 +542,16 @@ public final class InputMethodManager {
mCurId = res.id;
mBindSequence = res.sequence;
}
- startInputInner(InputMethodClient.START_INPUT_REASON_BOUND_TO_IMMS,
- null, 0, 0, 0);
+ startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
return;
}
case MSG_UNBIND: {
final int sequence = msg.arg1;
- @InputMethodClient.UnbindReason
+ @UnbindReason
final int reason = msg.arg2;
if (DEBUG) {
Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
- " reason=" + InputMethodClient.getUnbindReason(reason));
+ " reason=" + InputMethodDebug.unbindReasonToString(reason));
}
final boolean startInput;
synchronized (mH) {
@@ -567,8 +568,7 @@ public final class InputMethodManager {
}
if (startInput) {
startInputInner(
- InputMethodClient.START_INPUT_REASON_UNBOUND_FROM_IMMS, null, 0, 0,
- 0);
+ StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
}
return;
}
@@ -597,9 +597,8 @@ public final class InputMethodManager {
// handling this message.
if (mServedView != null && canStartInput(mServedView)) {
if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
- final int reason = active ?
- InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
- InputMethodClient.START_INPUT_REASON_DEACTIVATED_BY_IMMS;
+ final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
+ : StartInputReason.DEACTIVATED_BY_IMMS;
startInputInner(reason, null, 0, 0, 0);
}
}
@@ -696,7 +695,7 @@ public final class InputMethodManager {
}
@Override
- public void onUnbindMethod(int sequence, @InputMethodClient.UnbindReason int unbindReason) {
+ public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
}
@@ -1386,11 +1385,10 @@ public final class InputMethodManager {
mServedConnecting = true;
}
- startInputInner(InputMethodClient.START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, null, 0,
- 0, 0);
+ startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
}
- boolean startInputInner(@InputMethodClient.StartInputReason final int startInputReason,
+ boolean startInputInner(@StartInputReason int startInputReason,
@Nullable IBinder windowGainingFocus, int controlFlags, int softInputMode,
int windowFlags) {
final View view;
@@ -1400,7 +1398,7 @@ public final class InputMethodManager {
// Make sure we have a window token for the served view.
if (DEBUG) {
Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
- " reason=" + InputMethodClient.getStartInputReason(startInputReason));
+ " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
}
if (view == null) {
if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
@@ -1519,7 +1517,7 @@ public final class InputMethodManager {
if (res == null) {
Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
+ " null. startInputReason="
- + InputMethodClient.getStartInputReason(startInputReason)
+ + InputMethodDebug.startInputReasonToString(startInputReason)
+ " editorInfo=" + tba
+ " controlFlags=#" + Integer.toHexString(controlFlags));
return false;
@@ -1654,7 +1652,7 @@ public final class InputMethodManager {
@UnsupportedAppUsage
public void checkFocus() {
if (checkFocusNoStartInput(false)) {
- startInputInner(InputMethodClient.START_INPUT_REASON_CHECK_FOCUS, null, 0, 0, 0);
+ startInputInner(StartInputReason.CHECK_FOCUS, null, 0, 0, 0);
}
}
@@ -1717,7 +1715,7 @@ public final class InputMethodManager {
boolean forceNewFocus = false;
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
- + " softInputMode=" + InputMethodClient.softInputModeToString(softInputMode)
+ + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
+ " first=" + first + " flags=#"
+ Integer.toHexString(windowFlags));
if (mRestartOnNextWindowFocus) {
@@ -1744,8 +1742,8 @@ public final class InputMethodManager {
// should be done in conjunction with telling the system service
// about the window gaining focus, to help make the transition
// smooth.
- if (startInputInner(InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN,
- rootView.getWindowToken(), controlFlags, softInputMode, windowFlags)) {
+ if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
+ controlFlags, softInputMode, windowFlags)) {
return;
}
}
@@ -1756,7 +1754,7 @@ public final class InputMethodManager {
try {
if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
mService.startInputOrWindowGainedFocus(
- InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
null, 0 /* missingMethodFlags */,
rootView.getContext().getApplicationInfo().targetSdkVersion);
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 69d7202c4da8..300bb6fd4890 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -299,7 +299,7 @@ public class WebViewClient {
/**
* The resource was blocked because it may trick the user into a billing agreement.
*
- * <p>This constant is only used when targetSdkVersion is greater than {@link
+ * <p>This constant is only used when targetSdkVersion is at least {@link
* android.os.Build.VERSION_CODES#Q}. Otherwise, {@link #SAFE_BROWSING_THREAT_UNKNOWN} is used
* instead.
*/
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
new file mode 100644
index 000000000000..a5dc3d1b7138
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.inputmethod;
+
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+
+/**
+ * Provides useful methods for debugging.
+ */
+public final class InputMethodDebug {
+ /**
+ * Not intended to be instantiated.
+ */
+ private InputMethodDebug() {
+ }
+
+ /**
+ * Converts {@link StartInputReason} to {@link String} for debug logging.
+ *
+ * @param reason integer constant for {@link StartInputReason}.
+ * @return {@link String} message corresponds for the given {@code reason}.
+ */
+ public static String startInputReasonToString(@StartInputReason int reason) {
+ switch (reason) {
+ case StartInputReason.UNSPECIFIED:
+ return "UNSPECIFIED";
+ case StartInputReason.WINDOW_FOCUS_GAIN:
+ return "WINDOW_FOCUS_GAIN";
+ case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY:
+ return "WINDOW_FOCUS_GAIN_REPORT_ONLY";
+ case StartInputReason.APP_CALLED_RESTART_INPUT_API:
+ return "APP_CALLED_RESTART_INPUT_API";
+ case StartInputReason.CHECK_FOCUS:
+ return "CHECK_FOCUS";
+ case StartInputReason.BOUND_TO_IMMS:
+ return "BOUND_TO_IMMS";
+ case StartInputReason.UNBOUND_FROM_IMMS:
+ return "UNBOUND_FROM_IMMS";
+ case StartInputReason.ACTIVATED_BY_IMMS:
+ return "ACTIVATED_BY_IMMS";
+ case StartInputReason.DEACTIVATED_BY_IMMS:
+ return "DEACTIVATED_BY_IMMS";
+ case StartInputReason.SESSION_CREATED_BY_IME:
+ return "SESSION_CREATED_BY_IME";
+ default:
+ return "Unknown=" + reason;
+ }
+ }
+
+ /**
+ * Converts {@link UnbindReason} to {@link String} for debug logging.
+ *
+ * @param reason integer constant for {@link UnbindReason}.
+ * @return {@link String} message corresponds for the given {@code reason}.
+ */
+ public static String unbindReasonToString(@UnbindReason int reason) {
+ switch (reason) {
+ case UnbindReason.UNSPECIFIED:
+ return "UNSPECIFIED";
+ case UnbindReason.SWITCH_CLIENT:
+ return "SWITCH_CLIENT";
+ case UnbindReason.SWITCH_IME:
+ return "SWITCH_IME";
+ case UnbindReason.DISCONNECT_IME:
+ return "DISCONNECT_IME";
+ case UnbindReason.NO_IME:
+ return "NO_IME";
+ case UnbindReason.SWITCH_IME_FAILED:
+ return "SWITCH_IME_FAILED";
+ case UnbindReason.SWITCH_USER:
+ return "SWITCH_USER";
+ default:
+ return "Unknown=" + reason;
+ }
+ }
+
+ /**
+ * Converts {@link SoftInputModeFlags} to {@link String} for debug logging.
+ *
+ * @param softInputMode integer constant for {@link SoftInputModeFlags}.
+ * @return {@link String} message corresponds for the given {@code softInputMode}.
+ */
+ public static String softInputModeToString(@SoftInputModeFlags int softInputMode) {
+ final StringBuilder sb = new StringBuilder();
+ final int state = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
+ final int adjust = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+ final boolean isForwardNav =
+ (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;
+
+ switch (state) {
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
+ sb.append("STATE_UNSPECIFIED");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
+ sb.append("STATE_UNCHANGED");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
+ sb.append("STATE_HIDDEN");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
+ sb.append("STATE_ALWAYS_HIDDEN");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
+ sb.append("STATE_VISIBLE");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
+ sb.append("STATE_ALWAYS_VISIBLE");
+ break;
+ default:
+ sb.append("STATE_UNKNOWN(");
+ sb.append(state);
+ sb.append(")");
+ break;
+ }
+
+ switch (adjust) {
+ case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED:
+ sb.append("|ADJUST_UNSPECIFIED");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE:
+ sb.append("|ADJUST_RESIZE");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN:
+ sb.append("|ADJUST_PAN");
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING:
+ sb.append("|ADJUST_NOTHING");
+ break;
+ default:
+ sb.append("|ADJUST_UNKNOWN(");
+ sb.append(adjust);
+ sb.append(")");
+ break;
+ }
+
+ if (isForwardNav) {
+ // This is a special bit that is set by the system only during the window navigation.
+ sb.append("|IS_FORWARD_NAVIGATION");
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/core/java/com/android/internal/inputmethod/StartInputReason.java b/core/java/com/android/internal/inputmethod/StartInputReason.java
new file mode 100644
index 000000000000..a01c45919b8f
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/StartInputReason.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.inputmethod;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Describes the reason why {@link android.view.inputmethod.InputMethodManager} is calling
+ * {@link com.android.internal.view.IInputMethodManager#startInputOrWindowGainedFocus}.
+ */
+@Retention(SOURCE)
+@IntDef(value = {
+ StartInputReason.UNSPECIFIED,
+ StartInputReason.WINDOW_FOCUS_GAIN,
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY,
+ StartInputReason.APP_CALLED_RESTART_INPUT_API,
+ StartInputReason.CHECK_FOCUS,
+ StartInputReason.BOUND_TO_IMMS,
+ StartInputReason.UNBOUND_FROM_IMMS,
+ StartInputReason.ACTIVATED_BY_IMMS,
+ StartInputReason.DEACTIVATED_BY_IMMS,
+ StartInputReason.SESSION_CREATED_BY_IME})
+public @interface StartInputReason {
+ /**
+ * Reason is not specified.
+ */
+ int UNSPECIFIED = 0;
+ /**
+ * {@link android.view.Window} gained focus and it made the focused {@link android.view.View}
+ * to (re)start a new connection.
+ */
+ int WINDOW_FOCUS_GAIN = 1;
+ /**
+ * {@link android.view.Window} gained focus but there is no {@link android.view.View} that is
+ * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports
+ * this window focus change event.
+ */
+ int WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
+ /**
+ * {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is
+ * either explicitly called by the application or indirectly called by some Framework class
+ * (e.g. {@link android.widget.EditText}).
+ */
+ int APP_CALLED_RESTART_INPUT_API = 3;
+ /**
+ * {@link android.view.View} requested a new connection because of view focus change.
+ */
+ int CHECK_FOCUS = 4;
+ /**
+ * {@link android.view.inputmethod.InputMethodManager} is responding to
+ * {@link com.android.internal.view.IInputMethodClient#onBindMethod}.
+ */
+ int BOUND_TO_IMMS = 5;
+ /**
+ * {@link android.view.inputmethod.InputMethodManager} is responding to
+ * {@link com.android.internal.view.IInputMethodClient#onUnbindMethod}.
+ */
+ int UNBOUND_FROM_IMMS = 6;
+ /**
+ * {@link android.view.inputmethod.InputMethodManager} is responding to
+ * {@link com.android.internal.view.IInputMethodClient#setActive}.
+ */
+ int ACTIVATED_BY_IMMS = 7;
+ /**
+ * {@link android.view.inputmethod.InputMethodManager} is responding to
+ * {@link com.android.internal.view.IInputMethodClient#setActive}.
+ */
+ int DEACTIVATED_BY_IMMS = 8;
+ /**
+ * {@link com.android.server.inputmethod.InputMethodManagerService} is responding to
+ * {@link com.android.internal.view.IInputSessionCallback#sessionCreated}.
+ */
+ int SESSION_CREATED_BY_IME = 9;
+}
diff --git a/core/java/com/android/internal/inputmethod/UnbindReason.java b/core/java/com/android/internal/inputmethod/UnbindReason.java
new file mode 100644
index 000000000000..f0f18f11abe7
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/UnbindReason.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.inputmethod;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Describes the reason why {@link com.android.server.inputmethod.InputMethodManagerService} is
+ * calling {@link com.android.internal.view.IInputMethodClient#onUnbindMethod}.
+ */
+@Retention(SOURCE)
+@IntDef(value = {
+ UnbindReason.UNSPECIFIED,
+ UnbindReason.SWITCH_CLIENT,
+ UnbindReason.SWITCH_IME,
+ UnbindReason.DISCONNECT_IME,
+ UnbindReason.NO_IME,
+ UnbindReason.SWITCH_IME_FAILED,
+ UnbindReason.SWITCH_USER})
+public @interface UnbindReason {
+ /**
+ * Reason is not specified.
+ */
+ int UNSPECIFIED = 0;
+ /**
+ * When a new IME client becomes active, the previous IME client will unbound from the current
+ * IME.
+ */
+ int SWITCH_CLIENT = 1;
+ /**
+ * Before a new IME becomes active, the current IME client be unbound from the previous IME.
+ */
+ int SWITCH_IME = 2;
+ /**
+ * When the current IME is disconnected, the current IME client will be unbound.
+ */
+ int DISCONNECT_IME = 3;
+ /**
+ * When the system loses the last enabled IME, the current IME client will be unbound.
+ */
+ int NO_IME = 4;
+ /**
+ * When the system failed to switch to another IME, the current IME client will be unbound.
+ */
+ int SWITCH_IME_FAILED = 5;
+ /**
+ * When a new user becomes foreground, the previous IME client will be unbound from the previous
+ * user's active IME.
+ */
+ int SWITCH_USER = 6;
+}
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 46667d1ea688..2442d0b84bd6 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -158,7 +158,7 @@ public class KernelWakelockReader {
PROC_WAKELOCKS_FORMAT,
nameStringArray, wlData, null);
- name = nameStringArray[0];
+ name = nameStringArray[0].trim();
count = (int) wlData[1];
if (wakeup_sources) {
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 2618356d7a09..17b2bc46de36 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -24,7 +24,6 @@ import com.android.internal.view.InputBindResult;
*/
oneway interface IInputMethodClient {
void onBindMethod(in InputBindResult res);
- // unbindReason corresponds to InputMethodClient.UnbindReason.
void onUnbindMethod(int sequence, int unbindReason);
void setActive(boolean active, boolean fullscreen);
void reportFullscreenMode(boolean fullscreen);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 34e850130b50..29c55c234677 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -54,7 +54,7 @@ interface IInputMethodManager {
// has gained focus, and if 'attribute' is non-null then also does startInput.
// @NonNull
InputBindResult startInputOrWindowGainedFocus(
- /* @InputMethodClient.StartInputReason */ int startInputReason,
+ /* @StartInputReason */ int startInputReason,
in IInputMethodClient client, in IBinder windowToken, int controlFlags,
/* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
int windowFlags, in EditorInfo attribute, IInputContext inputContext,
diff --git a/core/java/com/android/internal/view/InputMethodClient.java b/core/java/com/android/internal/view/InputMethodClient.java
deleted file mode 100644
index bbd33a258e18..000000000000
--- a/core/java/com/android/internal/view/InputMethodClient.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2015 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 com.android.internal.view;
-
-import android.annotation.IntDef;
-import android.view.WindowManager.LayoutParams;
-import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-
-import java.lang.annotation.Retention;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-public final class InputMethodClient {
- public static final int START_INPUT_REASON_UNSPECIFIED = 0;
- public static final int START_INPUT_REASON_WINDOW_FOCUS_GAIN = 1;
- public static final int START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
- public static final int START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API = 3;
- public static final int START_INPUT_REASON_CHECK_FOCUS = 4;
- public static final int START_INPUT_REASON_BOUND_TO_IMMS = 5;
- public static final int START_INPUT_REASON_UNBOUND_FROM_IMMS = 6;
- public static final int START_INPUT_REASON_ACTIVATED_BY_IMMS = 7;
- public static final int START_INPUT_REASON_DEACTIVATED_BY_IMMS = 8;
- public static final int START_INPUT_REASON_SESSION_CREATED_BY_IME = 9;
-
- @Retention(SOURCE)
- @IntDef({START_INPUT_REASON_UNSPECIFIED, START_INPUT_REASON_WINDOW_FOCUS_GAIN,
- START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY,
- START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, START_INPUT_REASON_CHECK_FOCUS,
- START_INPUT_REASON_BOUND_TO_IMMS, START_INPUT_REASON_ACTIVATED_BY_IMMS,
- START_INPUT_REASON_DEACTIVATED_BY_IMMS, START_INPUT_REASON_SESSION_CREATED_BY_IME})
- public @interface StartInputReason {}
-
- public static String getStartInputReason(@StartInputReason final int reason) {
- switch (reason) {
- case START_INPUT_REASON_UNSPECIFIED:
- return "UNSPECIFIED";
- case START_INPUT_REASON_WINDOW_FOCUS_GAIN:
- return "WINDOW_FOCUS_GAIN";
- case START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY:
- return "WINDOW_FOCUS_GAIN_REPORT_ONLY";
- case START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API:
- return "APP_CALLED_RESTART_INPUT_API";
- case START_INPUT_REASON_CHECK_FOCUS:
- return "CHECK_FOCUS";
- case START_INPUT_REASON_BOUND_TO_IMMS:
- return "BOUND_TO_IMMS";
- case START_INPUT_REASON_UNBOUND_FROM_IMMS:
- return "UNBOUND_FROM_IMMS";
- case START_INPUT_REASON_ACTIVATED_BY_IMMS:
- return "ACTIVATED_BY_IMMS";
- case START_INPUT_REASON_DEACTIVATED_BY_IMMS:
- return "DEACTIVATED_BY_IMMS";
- case START_INPUT_REASON_SESSION_CREATED_BY_IME:
- return "SESSION_CREATED_BY_IME";
- default:
- return "Unknown=" + reason;
- }
- }
-
- public static final int UNBIND_REASON_UNSPECIFIED = 0;
- public static final int UNBIND_REASON_SWITCH_CLIENT = 1;
- public static final int UNBIND_REASON_SWITCH_IME = 2;
- public static final int UNBIND_REASON_DISCONNECT_IME = 3;
- public static final int UNBIND_REASON_NO_IME = 4;
- public static final int UNBIND_REASON_SWITCH_IME_FAILED = 5;
- public static final int UNBIND_REASON_SWITCH_USER = 6;
-
- @Retention(SOURCE)
- @IntDef({UNBIND_REASON_UNSPECIFIED, UNBIND_REASON_SWITCH_CLIENT, UNBIND_REASON_SWITCH_IME,
- UNBIND_REASON_DISCONNECT_IME, UNBIND_REASON_NO_IME, UNBIND_REASON_SWITCH_IME_FAILED,
- UNBIND_REASON_SWITCH_USER})
- public @interface UnbindReason {}
-
- public static String getUnbindReason(@UnbindReason final int reason) {
- switch (reason) {
- case UNBIND_REASON_UNSPECIFIED:
- return "UNSPECIFIED";
- case UNBIND_REASON_SWITCH_CLIENT:
- return "SWITCH_CLIENT";
- case UNBIND_REASON_SWITCH_IME:
- return "SWITCH_IME";
- case UNBIND_REASON_DISCONNECT_IME:
- return "DISCONNECT_IME";
- case UNBIND_REASON_NO_IME:
- return "NO_IME";
- case UNBIND_REASON_SWITCH_IME_FAILED:
- return "SWITCH_IME_FAILED";
- case UNBIND_REASON_SWITCH_USER:
- return "SWITCH_USER";
- default:
- return "Unknown=" + reason;
- }
- }
-
- public static String softInputModeToString(@SoftInputModeFlags final int softInputMode) {
- final StringBuilder sb = new StringBuilder();
- final int state = softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE;
- final int adjust = softInputMode & LayoutParams.SOFT_INPUT_MASK_ADJUST;
- final boolean isForwardNav =
- (softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;
-
- switch (state) {
- case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
- sb.append("STATE_UNSPECIFIED");
- break;
- case LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
- sb.append("STATE_UNCHANGED");
- break;
- case LayoutParams.SOFT_INPUT_STATE_HIDDEN:
- sb.append("STATE_HIDDEN");
- break;
- case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
- sb.append("STATE_ALWAYS_HIDDEN");
- break;
- case LayoutParams.SOFT_INPUT_STATE_VISIBLE:
- sb.append("STATE_VISIBLE");
- break;
- case LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
- sb.append("STATE_ALWAYS_VISIBLE");
- break;
- default:
- sb.append("STATE_UNKNOWN(");
- sb.append(state);
- sb.append(")");
- break;
- }
-
- switch (adjust) {
- case LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED:
- sb.append("|ADJUST_UNSPECIFIED");
- break;
- case LayoutParams.SOFT_INPUT_ADJUST_RESIZE:
- sb.append("|ADJUST_RESIZE");
- break;
- case LayoutParams.SOFT_INPUT_ADJUST_PAN:
- sb.append("|ADJUST_PAN");
- break;
- case LayoutParams.SOFT_INPUT_ADJUST_NOTHING:
- sb.append("|ADJUST_NOTHING");
- break;
- default:
- sb.append("|ADJUST_UNKNOWN(");
- sb.append(adjust);
- sb.append(")");
- break;
- }
-
- if (isForwardNav) {
- // This is a special bit that is set by the system only during the window navigation.
- sb.append("|IS_FORWARD_NAVIGATION");
- }
-
- return sb.toString();
- }
-}
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 0022c931c45e..c6e4c154b41e 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -141,7 +141,7 @@ uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
// select only flags that might affect text layout
flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
SkPaint::kSubpixelText_Flag | SkPaint::kEmbeddedBitmapText_Flag |
- SkPaint::kAutoHinting_Flag | SkPaint::kVerticalText_Flag);
+ SkPaint::kAutoHinting_Flag);
flags |= (hinting << 16);
return flags;
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index e67b100d840d..474b671c0c2b 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -538,8 +538,13 @@ public class MtpDatabase implements AutoCloseable {
MtpPropertyGroup propertyGroup;
for (MtpStorageManager.MtpObject obj : objs) {
if (property == 0xffffffff) {
+ if (format == 0 && handle != 0 && handle != 0xffffffff) {
+ // return properties based on the object's format
+ format = obj.getFormat();
+ }
// Get all properties supported by this object
- propertyGroup = mPropertyGroupsByFormat.get(obj.getFormat());
+ // format should be the same between get & put
+ propertyGroup = mPropertyGroupsByFormat.get(format);
if (propertyGroup == null) {
int[] propertyList = getSupportedObjectProperties(format);
propertyGroup = new MtpPropertyGroup(mMediaProvider, mVolumeName,
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 3870124f295e..fa9ab1f72688 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -128,6 +128,7 @@ cc_library_shared {
"libmediametrics",
"libmediaplayer2",
"libmediaplayer2-protos",
+ "libmediandk_utils",
"libmediautils",
"libnetd_client", // for setNetworkForUser
"libprotobuf-cpp-lite",
diff --git a/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java b/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java
index 5782ea100070..31c9224a8489 100644
--- a/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java
@@ -66,7 +66,7 @@ public class AgingHelper {
public void onNotificationSeen(NotificationEntry entry) {
// user has strong opinions about this notification. we can't down rank it, so don't bother.
- if (entry.getChannel().isImportanceLocked()) {
+ if (entry.getChannel().hasUserSetImportance()) {
return;
}
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 3333e1592bfa..8f33a7016b39 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -25,7 +25,6 @@ import static android.service.notification.NotificationListenerService.Ranking
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
-import android.app.AlarmManager;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -224,8 +223,9 @@ public class Assistant extends NotificationAssistantService {
}
/** A convenience helper for creating an adjustment for an SBN. */
+ @VisibleForTesting
@Nullable
- private Adjustment createEnqueuedNotificationAdjustment(
+ Adjustment createEnqueuedNotificationAdjustment(
@NonNull NotificationEntry entry,
@NonNull ArrayList<Notification.Action> smartActions,
@NonNull ArrayList<CharSequence> smartReplies) {
@@ -237,7 +237,9 @@ public class Assistant extends NotificationAssistantService {
signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
}
if (mNotificationCategorizer.shouldSilence(entry)) {
- signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
+ final int importance = entry.getImportance() < IMPORTANCE_LOW ? entry.getImportance()
+ : IMPORTANCE_LOW;
+ signals.putInt(KEY_IMPORTANCE, importance);
}
return new Adjustment(
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
index 2820232cdb38..2eb005a9b1fa 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
@@ -66,6 +66,7 @@ import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
+import java.util.ArrayList;
public class AssistantTest extends ServiceTestCase<Assistant> {
@@ -466,4 +467,12 @@ public class AssistantTest extends ServiceTestCase<Assistant> {
assertFalse(mAssistant.mLiveNotifications.containsKey(sbn.getKey()));
}
+
+ @Test
+ public void testAssistantNeverIncreasesImportanceWhenSuggestingSilent() throws Exception {
+ StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "min notif!", null);
+ Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(new NotificationEntry(
+ mPackageManager, sbn, P1C3), new ArrayList<>(), new ArrayList<>());
+ assertEquals(IMPORTANCE_MIN, adjust.getSignals().getInt(Adjustment.KEY_IMPORTANCE));
+ }
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index b2be5e6b5f8e..793a1778f900 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -1270,26 +1270,36 @@ public class VibratorService extends IVibratorService.Stub
public int onCommand(String cmd) {
if ("vibrate".equals(cmd)) {
return runVibrate();
+ } else if ("prebaked".equals(cmd)) {
+ return runPrebaked();
}
return handleDefaultCommands(cmd);
}
+ private boolean checkDoNotDisturb() {
+ try {
+ final int zenMode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE);
+ if (zenMode != Settings.Global.ZEN_MODE_OFF) {
+ try (PrintWriter pw = getOutPrintWriter();) {
+ pw.print("Ignoring because device is on DND mode ");
+ pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_",
+ zenMode));
+ return true;
+ }
+ }
+ } catch (SettingNotFoundException e) {
+ // ignore
+ }
+
+ return false;
+ }
+
private int runVibrate() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runVibrate");
try {
- try {
- final int zenMode = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.ZEN_MODE);
- if (zenMode != Settings.Global.ZEN_MODE_OFF) {
- try (PrintWriter pw = getOutPrintWriter();) {
- pw.print("Ignoring because device is on DND mode ");
- pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_",
- zenMode));
- return 0;
- }
- }
- } catch (SettingNotFoundException e) {
- // ignore
+ if (checkDoNotDisturb()) {
+ return 0;
}
final long duration = Long.parseLong(getNextArgRequired());
@@ -1311,6 +1321,30 @@ public class VibratorService extends IVibratorService.Stub
}
}
+ private int runPrebaked() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runPrebaked");
+ try {
+ if (checkDoNotDisturb()) {
+ return 0;
+ }
+
+ final int id = Integer.parseInt(getNextArgRequired());
+
+ String description = getNextArg();
+ if (description == null) {
+ description = "Shell command";
+ }
+
+ VibrationEffect effect =
+ VibrationEffect.get(id, false);
+ vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
+ "Shell Command", mToken);
+ return 0;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
+
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
@@ -1321,6 +1355,9 @@ public class VibratorService extends IVibratorService.Stub
pw.println(" vibrate duration [description]");
pw.println(" Vibrates for duration milliseconds; ignored when device is on DND ");
pw.println(" (Do Not Disturb) mode.");
+ pw.println(" prebaked effect-id [description]");
+ pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
+ pw.println(" (Do Not Disturb) mode.");
pw.println("");
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 723531236312..4070bca199e0 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3620,7 +3620,7 @@ public final class ActiveServices {
nextTime = sr.executingStart;
}
}
- if (timeout != null && mAm.mLruProcesses.contains(proc)) {
+ if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {
Slog.w(TAG, "Timeout executing service: " + timeout);
StringWriter sw = new StringWriter();
PrintWriter pw = new FastPrintWriter(sw, false, 1024);
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 9a47553bf446..ede13ef66ac4 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -873,6 +873,52 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
return null;
}
+ ActivityRecord topRunningActivity() {
+ return topRunningActivity(false /* considerKeyguardState */);
+ }
+
+ /**
+ * Returns the top running activity in the focused stack. In the case the focused stack has no
+ * such activity, the next focusable stack on this display is returned.
+ *
+ * @param considerKeyguardState Indicates whether the locked state should be considered. if
+ * {@code true} and the keyguard is locked, only activities that
+ * can be shown on top of the keyguard will be considered.
+ * @return The top running activity. {@code null} if none is available.
+ */
+ ActivityRecord topRunningActivity(boolean considerKeyguardState) {
+ ActivityRecord topRunning = null;
+ final ActivityStack focusedStack = getFocusedStack();
+ if (focusedStack != null) {
+ topRunning = focusedStack.topRunningActivityLocked();
+ }
+
+ // Look in other focusable stacks.
+ if (topRunning == null) {
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ final ActivityStack stack = mStacks.get(i);
+ // Only consider focusable stacks other than the current focused one.
+ if (stack == focusedStack || !stack.isFocusable()) {
+ continue;
+ }
+ topRunning = stack.topRunningActivityLocked();
+ if (topRunning != null) {
+ break;
+ }
+ }
+ }
+
+ // This activity can be considered the top running activity if we are not considering
+ // the locked state, the keyguard isn't locked, or we can show when locked.
+ if (topRunning != null && considerKeyguardState
+ && mSupervisor.getKeyguardController().isKeyguardLocked()
+ && !topRunning.canShowWhenLocked()) {
+ return null;
+ }
+
+ return topRunning;
+ }
+
int getIndexOf(ActivityStack stack) {
return mStacks.indexOf(stack);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c27ec6f107f2..d56b523f07aa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -26,7 +26,6 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
-import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
import static android.app.AppOpsManager.OP_NONE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -47,8 +46,6 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
-import static android.os.Process.FIRST_ISOLATED_UID;
-import static android.os.Process.LAST_ISOLATED_UID;
import static android.os.Process.NFC_UID;
import static android.os.Process.PHONE_UID;
import static android.os.Process.PROC_CHAR;
@@ -67,9 +64,7 @@ import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
import static android.os.Process.THREAD_GROUP_DEFAULT;
import static android.os.Process.THREAD_GROUP_RESTRICTED;
import static android.os.Process.THREAD_GROUP_TOP_APP;
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
-import static android.os.Process.getFreeMemory;
import static android.os.Process.getPidsForCommands;
import static android.os.Process.getTotalMemory;
import static android.os.Process.getUidForPid;
@@ -84,7 +79,6 @@ import static android.os.Process.sendSignal;
import static android.os.Process.setProcessGroup;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
-import static android.os.Process.startWebView;
import static android.os.Process.zygoteProcess;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
@@ -193,6 +187,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProcessMemoryState;
import android.app.ProfilerInfo;
+import android.app.WaitResult;
import android.app.WindowConfiguration.ActivityType;
import android.app.WindowConfiguration.WindowingMode;
import android.app.backup.IBackupManager;
@@ -262,7 +257,6 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.Process;
-import android.os.Process.ProcessStartResult;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -278,7 +272,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.os.storage.StorageManager;
-import android.os.storage.StorageManagerInternal;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -288,7 +281,6 @@ import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.EventLog;
import android.util.Log;
-import android.util.LongSparseArray;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -324,7 +316,6 @@ import com.android.internal.os.ByteTransferPipe;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
-import com.android.internal.os.Zygote;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -355,7 +346,6 @@ import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
-import com.android.server.pm.dex.DexManager;
import com.android.server.uri.GrantUri;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.PriorityDump;
@@ -404,24 +394,24 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
public static final int TOP_APP_PRIORITY_BOOST = -10;
- private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
+ static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
private static final String TAG_BACKUP = TAG + POSTFIX_BACKUP;
private static final String TAG_BROADCAST = TAG + POSTFIX_BROADCAST;
private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
- private static final String TAG_LRU = TAG + POSTFIX_LRU;
+ static final String TAG_LRU = TAG + POSTFIX_LRU;
private static final String TAG_MU = TAG + POSTFIX_MU;
private static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
private static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
private static final String TAG_POWER = TAG + POSTFIX_POWER;
private static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
- private static final String TAG_PROCESSES = TAG + POSTFIX_PROCESSES;
+ static final String TAG_PROCESSES = TAG + POSTFIX_PROCESSES;
private static final String TAG_PROVIDER = TAG + POSTFIX_PROVIDER;
- private static final String TAG_PSS = TAG + POSTFIX_PSS;
+ static final String TAG_PSS = TAG + POSTFIX_PSS;
private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
- private static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
+ static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
// Mock "pretend we're idle now" broadcast action to the job scheduler; declared
// here so that while the job scheduler can depend on AMS, the other way around
@@ -489,7 +479,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private static final int SLOW_UID_OBSERVER_THRESHOLD_MS = 20;
// Necessary ApplicationInfo flags to mark an app as persistent
- private static final int PERSISTENT_MASK =
+ static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
// Intent sent when remote bugreport collection has been completed
@@ -627,46 +617,12 @@ public class ActivityManagerService extends IActivityManager.Stub
final ProcessList mProcessList = new ProcessList();
/**
- * All of the applications we currently have running organized by name.
- * The keys are strings of the application package name (as
- * returned by the package manager), and the keys are ApplicationRecord
- * objects.
- */
- final MyProcessMap mProcessNames = new MyProcessMap();
- final class MyProcessMap extends ProcessMap<ProcessRecord> {
- @Override
- public ProcessRecord put(String name, int uid, ProcessRecord value) {
- final ProcessRecord r = super.put(name, uid, value);
- mAtmInternal.onProcessAdded(r.getWindowProcessController());
- return r;
- }
-
- @Override
- public ProcessRecord remove(String name, int uid) {
- final ProcessRecord r = super.remove(name, uid);
- mAtmInternal.onProcessRemoved(name, uid);
- return r;
- }
- }
-
- /**
* Tracking long-term execution of processes to look for abuse and other
* bad app behavior.
*/
final ProcessStatsService mProcessStats;
/**
- * The currently running isolated processes.
- */
- final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
-
- /**
- * Counter for assigning isolated process uids, to avoid frequently reusing the
- * same ones.
- */
- int mNextIsolatedProcessUid = 0;
-
- /**
* Non-persistent appId whitelist for background restrictions
*/
int[] mBackgroundAppIdWhitelist = new int[] {
@@ -767,28 +723,6 @@ public class ActivityManagerService extends IActivityManager.Stub
final ArrayList<ProcessRecord> mPersistentStartingProcesses = new ArrayList<ProcessRecord>();
/**
- * Processes that are being forcibly torn down.
- */
- final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();
-
- /**
- * List of running applications, sorted by recent usage.
- * The first entry in the list is the least recently used.
- */
- final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
-
- /**
- * Where in mLruProcesses that the processes hosting activities start.
- */
- int mLruProcessActivityStart = 0;
-
- /**
- * Where in mLruProcesses that the processes hosting services start.
- * This is after (lower index) than mLruProcessesActivityStart.
- */
- int mLruProcessServiceStart = 0;
-
- /**
* List of processes that should gc as soon as things are idle.
*/
final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<ProcessRecord>();
@@ -1104,11 +1038,6 @@ public class ActivityManagerService extends IActivityManager.Stub
int mAdjSeq = 0;
/**
- * Current sequence id for process LRU updating.
- */
- int mLruSeq = 0;
-
- /**
* Keep track of the non-cached/empty process we last found, to help
* determine how to distribute cached/empty processes next time.
*/
@@ -1220,31 +1149,6 @@ public class ActivityManagerService extends IActivityManager.Stub
private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
- /**
- * A global counter for generating sequence numbers.
- * This value will be used when incrementing sequence numbers in individual uidRecords.
- *
- * Having a global counter ensures that seq numbers are monotonically increasing for a
- * particular uid even when the uidRecord is re-created.
- */
- @GuardedBy("this")
- @VisibleForTesting
- long mProcStateSeqCounter = 0;
-
- /**
- * A global counter for generating sequence numbers to uniquely identify pending process starts.
- */
- @GuardedBy("this")
- private long mProcStartSeqCounter = 0;
-
- /**
- * Contains {@link ProcessRecord} objects for pending process starts.
- *
- * Mapping: {@link #mProcStartSeqCounter} -> {@link ProcessRecord}
- */
- @GuardedBy("this")
- private final LongSparseArray<ProcessRecord> mPendingStarts = new LongSparseArray<>();
-
private final Injector mInjector;
static final class ProcessChangeItem {
@@ -1432,9 +1336,6 @@ public class ActivityManagerService extends IActivityManager.Stub
static final String SERVICE_RECORD_KEY = "servicerecord";
- static ServiceThread sKillThread = null;
- static KillHandler sKillHandler = null;
-
long mLastMemUsageReportTime = 0;
/**
@@ -1471,30 +1372,6 @@ public class ActivityManagerService extends IActivityManager.Stub
return mActivityTaskManager.getGlobalConfiguration();
}
- final class KillHandler extends Handler {
- static final int KILL_PROCESS_GROUP_MSG = 4000;
-
- public KillHandler(Looper looper) {
- super(looper, null, true);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case KILL_PROCESS_GROUP_MSG:
- {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup");
- Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- break;
-
- default:
- super.handleMessage(msg);
- }
- }
- }
-
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -1608,8 +1485,8 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case UPDATE_TIME_ZONE: {
synchronized (ActivityManagerService.this) {
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
+ for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mProcessList.mLruProcesses.get(i);
if (r.thread != null) {
try {
r.thread.updateTimeZone();
@@ -1622,16 +1499,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case CLEAR_DNS_CACHE_MSG: {
synchronized (ActivityManagerService.this) {
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
- try {
- r.thread.clearDnsCache();
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
- }
- }
- }
+ mProcessList.clearAllDnsCacheLocked();
}
} break;
case UPDATE_HTTP_PROXY_MSG: {
@@ -1647,19 +1515,7 @@ public class ActivityManagerService extends IActivityManager.Stub
pacFileUrl = proxy.getPacFileUrl();
}
synchronized (ActivityManagerService.this) {
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
- // Don't dispatch to isolated processes as they can't access
- // ConnectivityManager and don't have network privileges anyway.
- if (r.thread != null && !r.isolated) {
- try {
- r.thread.setHttpProxy(host, port, exclList, pacFileUrl);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to update http proxy for: " +
- r.info.processName);
- }
- }
- }
+ mProcessList.setAllHttpProxyLocked(host, port, exclList, pacFileUrl);
}
} break;
case PROC_START_TIMEOUT_MSG: {
@@ -1707,17 +1563,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// The user's time format preference might have changed.
// For convenience we re-use the Intent extra values.
synchronized (ActivityManagerService.this) {
- for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
- try {
- r.thread.updateTimePrefs(msg.arg1);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to update preferences for: "
- + r.info.processName);
- }
- }
- }
+ mProcessList.updateAllTimePrefsLocked(msg.arg1);
}
break;
}
@@ -1841,17 +1687,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
synchronized (ActivityManagerService.this) {
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
- try {
- r.thread.handleTrustStorageUpdate();
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to handle trust storage update for: " +
- r.info.processName);
- }
- }
- }
+ mProcessList.handleAllTrustStorageUpdateLocked();
}
} break;
}
@@ -1991,7 +1827,9 @@ public class ActivityManagerService extends IActivityManager.Stub
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
synchronized (this) {
- ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
+ ProcessRecord app = mProcessList.newProcessRecordLocked(info, info.processName,
+ false,
+ 0);
app.setPersistent(true);
app.pid = MY_PID;
app.getWindowProcessController().setPid(MY_PID);
@@ -2000,7 +1838,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
}
- updateLruProcessLocked(app, false, null);
+ mProcessList.updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
} catch (PackageManager.NameNotFoundException e) {
@@ -2268,24 +2106,38 @@ public class ActivityManagerService extends IActivityManager.Stub
@VisibleForTesting
public ActivityManagerService(Injector injector) {
+ this(injector, null /* handlerThread */);
+ }
+
+ /**
+ * Provides the basic functionality for activity task related tests when a handler thread is
+ * given to initialize the dependency members.
+ */
+ @VisibleForTesting
+ ActivityManagerService(Injector injector, ServiceThread handlerThread) {
+ final boolean hasHandlerThread = handlerThread != null;
mInjector = injector;
mContext = mInjector.getContext();
mUiContext = null;
mAppErrors = null;
- mAppOpsService = mInjector.getAppOpsService(null, null);
+ mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */);
mBatteryStatsService = null;
- mConstants = null;
- mHandler = null;
- mHandlerThread = null;
- mIntentFirewall = null;
+ mHandler = hasHandlerThread ? new MainHandler(handlerThread.getLooper()) : null;
+ mHandlerThread = handlerThread;
+ mConstants = hasHandlerThread ? new ActivityManagerConstants(this, mHandler) : null;
+ mIntentFirewall = hasHandlerThread
+ ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
mProcessCpuThread = null;
mProcessStats = null;
mProviderMap = null;
- mServices = null;
+ // For the usage of {@link ActiveServices#cleanUpServices} that may be invoked from
+ // {@link ActivityStackSupervisor#cleanUpRemovedTaskLocked}.
+ mServices = hasHandlerThread ? new ActiveServices(this) : null;
mSystemThread = null;
- mUiHandler = injector.getUiHandler(null);
- mUserController = null;
- mPendingIntentController = null;
+ mUiHandler = injector.getUiHandler(null /* service */);
+ mUserController = hasHandlerThread ? new UserController(this) : null;
+ mPendingIntentController = hasHandlerThread
+ ? new PendingIntentController(handlerThread.getLooper(), mUserController) : null;
mProcStartHandlerThread = null;
mProcStartHandler = null;
mHiddenApiBlacklist = null;
@@ -2318,13 +2170,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mConstants = new ActivityManagerConstants(this, mHandler);
- /* static; one-time init here */
- if (sKillHandler == null) {
- sKillThread = new ServiceThread(TAG + ":kill",
- THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
- sKillThread.start();
- sKillHandler = new KillHandler(sKillThread.getLooper());
- }
+ mProcessList.init(this);
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
@@ -2474,12 +2320,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (code == SYSPROPS_TRANSACTION) {
// We need to tell all apps about the system property change.
ArrayList<IBinder> procs = new ArrayList<IBinder>();
- synchronized(this) {
- final int NP = mProcessNames.getMap().size();
- for (int ip=0; ip<NP; ip++) {
- SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ synchronized (this) {
+ final int NP = mProcessList.mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ SparseArray<ProcessRecord> apps =
+ mProcessList.mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
- for (int ia=0; ia<NA; ia++) {
+ for (int ia = 0; ia < NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
if (app.thread != null) {
procs.add(app.thread.asBinder());
@@ -2729,329 +2576,21 @@ public class ActivityManagerService extends IActivityManager.Stub
mActivityTaskManager.unregisterTaskStackListener(listener);
}
- private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
- String what, Object obj, ProcessRecord srcApp) {
- app.lastActivityTime = now;
-
- if (app.hasActivitiesOrRecentTasks()) {
- // Don't want to touch dependent processes that are hosting activities.
- return index;
- }
-
- int lrui = mLruProcesses.lastIndexOf(app);
- if (lrui < 0) {
- Slog.wtf(TAG, "Adding dependent process " + app + " not on LRU list: "
- + what + " " + obj + " from " + srcApp);
- return index;
- }
-
- if (lrui >= index) {
- // Don't want to cause this to move dependent processes *back* in the
- // list as if they were less frequently used.
- return index;
- }
-
- if (lrui >= mLruProcessActivityStart) {
- // Don't want to touch dependent processes that are hosting activities.
- return index;
- }
-
- mLruProcesses.remove(lrui);
- if (index > 0) {
- index--;
- }
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Moving dep from " + lrui + " to " + index
- + " in LRU list: " + app);
- mLruProcesses.add(index, app);
- return index;
- }
-
- static void killProcessGroup(int uid, int pid) {
- if (sKillHandler != null) {
- sKillHandler.sendMessage(
- sKillHandler.obtainMessage(KillHandler.KILL_PROCESS_GROUP_MSG, uid, pid));
- } else {
- Slog.w(TAG, "Asked to kill process group before system bringup!");
- Process.killProcessGroup(uid, pid);
- }
+ final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
+ ProcessRecord client) {
+ mProcessList.updateLruProcessLocked(app, activityChange, client);
}
final void removeLruProcessLocked(ProcessRecord app) {
- int lrui = mLruProcesses.lastIndexOf(app);
- if (lrui >= 0) {
- if (!app.killed) {
- if (app.isPersistent()) {
- Slog.w(TAG, "Removing persistent process that hasn't been killed: " + app);
- } else {
- Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
- if (app.pid > 0) {
- killProcessQuiet(app.pid);
- killProcessGroup(app.uid, app.pid);
- } else {
- app.pendingStart = false;
- }
- }
- }
- if (lrui <= mLruProcessActivityStart) {
- mLruProcessActivityStart--;
- }
- if (lrui <= mLruProcessServiceStart) {
- mLruProcessServiceStart--;
- }
- mLruProcesses.remove(lrui);
- }
+ mProcessList.removeLruProcessLocked(app);
}
- final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
- ProcessRecord client) {
- final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities()
- || app.treatLikeActivity;
- final boolean hasService = false; // not impl yet. app.services.size() > 0;
- if (!activityChange && hasActivity) {
- // The process has activities, so we are only allowing activity-based adjustments
- // to move it. It should be kept in the front of the list with other
- // processes that have activities, and we don't want those to change their
- // order except due to activity operations.
- return;
- }
-
- mLruSeq++;
- final long now = SystemClock.uptimeMillis();
- app.lastActivityTime = now;
-
- // First a quick reject: if the app is already at the position we will
- // put it, then there is nothing to do.
- if (hasActivity) {
- final int N = mLruProcesses.size();
- if (N > 0 && mLruProcesses.get(N-1) == app) {
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top activity: " + app);
- return;
- }
- } else {
- if (mLruProcessServiceStart > 0
- && mLruProcesses.get(mLruProcessServiceStart-1) == app) {
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top other: " + app);
- return;
- }
- }
-
- int lrui = mLruProcesses.lastIndexOf(app);
-
- if (app.isPersistent() && lrui >= 0) {
- // We don't care about the position of persistent processes, as long as
- // they are in the list.
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, persistent: " + app);
- return;
- }
-
- /* In progress: compute new position first, so we can avoid doing work
- if the process is not actually going to move. Not yet working.
- int addIndex;
- int nextIndex;
- boolean inActivity = false, inService = false;
- if (hasActivity) {
- // Process has activities, put it at the very tipsy-top.
- addIndex = mLruProcesses.size();
- nextIndex = mLruProcessServiceStart;
- inActivity = true;
- } else if (hasService) {
- // Process has services, put it at the top of the service list.
- addIndex = mLruProcessActivityStart;
- nextIndex = mLruProcessServiceStart;
- inActivity = true;
- inService = true;
- } else {
- // Process not otherwise of interest, it goes to the top of the non-service area.
- addIndex = mLruProcessServiceStart;
- if (client != null) {
- int clientIndex = mLruProcesses.lastIndexOf(client);
- if (clientIndex < 0) Slog.d(TAG, "Unknown client " + client + " when updating "
- + app);
- if (clientIndex >= 0 && addIndex > clientIndex) {
- addIndex = clientIndex;
- }
- }
- nextIndex = addIndex > 0 ? addIndex-1 : addIndex;
- }
-
- Slog.d(TAG, "Update LRU at " + lrui + " to " + addIndex + " (act="
- + mLruProcessActivityStart + "): " + app);
- */
-
- if (lrui >= 0) {
- if (lrui < mLruProcessActivityStart) {
- mLruProcessActivityStart--;
- }
- if (lrui < mLruProcessServiceStart) {
- mLruProcessServiceStart--;
- }
- /*
- if (addIndex > lrui) {
- addIndex--;
- }
- if (nextIndex > lrui) {
- nextIndex--;
- }
- */
- mLruProcesses.remove(lrui);
- }
-
- /*
- mLruProcesses.add(addIndex, app);
- if (inActivity) {
- mLruProcessActivityStart++;
- }
- if (inService) {
- mLruProcessActivityStart++;
- }
- */
-
- int nextIndex;
- if (hasActivity) {
- final int N = mLruProcesses.size();
- if ((!app.hasActivities() || app.hasRecentTasks())
- && mLruProcessActivityStart < (N - 1)) {
- // Process doesn't have activities, but has clients with
- // activities... move it up, but one below the top (the top
- // should always have a real activity).
- if (DEBUG_LRU) Slog.d(TAG_LRU,
- "Adding to second-top of LRU activity list: " + app);
- mLruProcesses.add(N - 1, app);
- // To keep it from spamming the LRU list (by making a bunch of clients),
- // we will push down any other entries owned by the app.
- final int uid = app.info.uid;
- for (int i = N - 2; i > mLruProcessActivityStart; i--) {
- ProcessRecord subProc = mLruProcesses.get(i);
- if (subProc.info.uid == uid) {
- // We want to push this one down the list. If the process after
- // it is for the same uid, however, don't do so, because we don't
- // want them internally to be re-ordered.
- if (mLruProcesses.get(i - 1).info.uid != uid) {
- if (DEBUG_LRU) Slog.d(TAG_LRU,
- "Pushing uid " + uid + " swapping at " + i + ": "
- + mLruProcesses.get(i) + " : " + mLruProcesses.get(i - 1));
- ProcessRecord tmp = mLruProcesses.get(i);
- mLruProcesses.set(i, mLruProcesses.get(i - 1));
- mLruProcesses.set(i - 1, tmp);
- i--;
- }
- } else {
- // A gap, we can stop here.
- break;
- }
- }
- } else {
- // Process has activities, put it at the very tipsy-top.
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU activity list: " + app);
- mLruProcesses.add(app);
- }
- nextIndex = mLruProcessServiceStart;
- } else if (hasService) {
- // Process has services, put it at the top of the service list.
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU service list: " + app);
- mLruProcesses.add(mLruProcessActivityStart, app);
- nextIndex = mLruProcessServiceStart;
- mLruProcessActivityStart++;
- } else {
- // Process not otherwise of interest, it goes to the top of the non-service area.
- int index = mLruProcessServiceStart;
- if (client != null) {
- // If there is a client, don't allow the process to be moved up higher
- // in the list than that client.
- int clientIndex = mLruProcesses.lastIndexOf(client);
- if (DEBUG_LRU && clientIndex < 0) Slog.d(TAG_LRU, "Unknown client " + client
- + " when updating " + app);
- if (clientIndex <= lrui) {
- // Don't allow the client index restriction to push it down farther in the
- // list than it already is.
- clientIndex = lrui;
- }
- if (clientIndex >= 0 && index > clientIndex) {
- index = clientIndex;
- }
- }
- if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding at " + index + " of LRU list: " + app);
- mLruProcesses.add(index, app);
- nextIndex = index-1;
- mLruProcessActivityStart++;
- mLruProcessServiceStart++;
- }
-
- // If the app is currently using a content provider or service,
- // bump those processes as well.
- for (int j=app.connections.size()-1; j>=0; j--) {
- ConnectionRecord cr = app.connections.valueAt(j);
- if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
- && cr.binding.service.app != null
- && cr.binding.service.app.lruSeq != mLruSeq
- && !cr.binding.service.app.isPersistent()) {
- nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
- "service connection", cr, app);
- }
- }
- for (int j=app.conProviders.size()-1; j>=0; j--) {
- ContentProviderRecord cpr = app.conProviders.get(j).provider;
- if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.isPersistent()) {
- nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
- "provider reference", cpr, app);
- }
- }
+ final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
+ return mProcessList.getProcessRecordLocked(processName, uid, keepIfLarge);
}
- final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
- if (uid == SYSTEM_UID) {
- // The system gets to run in any process. If there are multiple
- // processes with the same uid, just pick the first (this
- // should never happen).
- SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
- if (procs == null) return null;
- final int procCount = procs.size();
- for (int i = 0; i < procCount; i++) {
- final int procUid = procs.keyAt(i);
- if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
- // Don't use an app process or different user process for system component.
- continue;
- }
- return procs.valueAt(i);
- }
- }
- ProcessRecord proc = mProcessNames.get(processName, uid);
- if (false && proc != null && !keepIfLarge
- && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
- && proc.lastCachedPss >= 4000) {
- // Turn this condition on to cause killing to happen regularly, for testing.
- if (proc.baseProcessTracker != null) {
- proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
- for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
- ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
- StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
- proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
- proc.lastCachedPss, holder.appVersion);
- }
- }
- proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
- } else if (proc != null && !keepIfLarge
- && mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
- && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
- if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc.lastCachedPss);
- if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) {
- if (proc.baseProcessTracker != null) {
- proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
- for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
- ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
- StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
- proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
- proc.lastCachedPss, holder.appVersion);
- }
- }
- proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
- }
- }
- return proc;
+ final ProcessMap<ProcessRecord> getProcessNames() {
+ return mProcessList.mProcessNames;
}
void notifyPackageUse(String packageName, int reason) {
@@ -3078,7 +2617,7 @@ public class ActivityManagerService extends IActivityManager.Stub
info.packageName = "android";
info.seInfoUser = SELinuxUtil.COMPLETE_STR;
info.targetSdkVersion = Build.VERSION.SDK_INT;
- ProcessRecord proc = startProcessLocked(processName, info /* info */,
+ ProcessRecord proc = mProcessList.startProcessLocked(processName, info /* info */,
false /* knownToBeDead */, 0 /* intentFlags */, "" /* hostingType */,
null /* hostingName */, true /* allowWhileBooting */, true /* isolated */,
uid, true /* keepIfLarge */, abiOverride, entryPoint, entryPointArgs,
@@ -3092,548 +2631,17 @@ public class ActivityManagerService extends IActivityManager.Stub
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
- return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
+ return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
+ hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
- @GuardedBy("this")
- final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
- boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
- boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
- String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
- long startTime = SystemClock.elapsedRealtime();
- ProcessRecord app;
- if (!isolated) {
- app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
- checkTime(startTime, "startProcess: after getProcessRecord");
-
- if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
- // If we are in the background, then check to see if this process
- // is bad. If so, we will just silently fail.
- if (mAppErrors.isBadProcessLocked(info)) {
- if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
- + "/" + info.processName);
- return null;
- }
- } else {
- // When the user is explicitly starting a process, then clear its
- // crash count so that we won't make it bad until they see at
- // least one crash dialog again, and make the process good again
- // if it had been bad.
- if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
- + "/" + info.processName);
- mAppErrors.resetProcessCrashTimeLocked(info);
- if (mAppErrors.isBadProcessLocked(info)) {
- EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
- UserHandle.getUserId(info.uid), info.uid,
- info.processName);
- mAppErrors.clearBadProcessLocked(info);
- if (app != null) {
- app.bad = false;
- }
- }
- }
- } else {
- // If this is an isolated process, it can't re-use an existing process.
- app = null;
- }
-
- // We don't have to do anything more if:
- // (1) There is an existing application record; and
- // (2) The caller doesn't think it is dead, OR there is no thread
- // object attached to it so we know it couldn't have crashed; and
- // (3) There is a pid assigned to it, so it is either starting or
- // already running.
- if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
- + " app=" + app + " knownToBeDead=" + knownToBeDead
- + " thread=" + (app != null ? app.thread : null)
- + " pid=" + (app != null ? app.pid : -1));
- if (app != null && app.pid > 0) {
- if ((!knownToBeDead && !app.killed) || app.thread == null) {
- // We already have the app running, or are waiting for it to
- // come up (we have a pid but not yet its thread), so keep it.
- if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
- // If this is a new package in the process, add the package to the list
- app.addPackage(info.packageName, info.versionCode, mProcessStats);
- checkTime(startTime, "startProcess: done, added package to proc");
- return app;
- }
-
- // An application record is attached to a previous process,
- // clean it up now.
- if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
- checkTime(startTime, "startProcess: bad proc running, killing");
- killProcessGroup(app.uid, app.pid);
- handleAppDiedLocked(app, true, true);
- checkTime(startTime, "startProcess: done killing old proc");
- }
-
- String hostingNameStr = hostingName != null
- ? hostingName.flattenToShortString() : null;
-
- if (app == null) {
- checkTime(startTime, "startProcess: creating new process record");
- app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
- if (app == null) {
- Slog.w(TAG, "Failed making new process record for "
- + processName + "/" + info.uid + " isolated=" + isolated);
- return null;
- }
- app.crashHandler = crashHandler;
- app.isolatedEntryPoint = entryPoint;
- app.isolatedEntryPointArgs = entryPointArgs;
- checkTime(startTime, "startProcess: done creating new process record");
- } else {
- // If this is a new package in the process, add the package to the list
- app.addPackage(info.packageName, info.versionCode, mProcessStats);
- checkTime(startTime, "startProcess: added package to existing proc");
- }
-
- // If the system is not ready yet, then hold off on starting this
- // process until it is.
- if (!mProcessesReady
- && !isAllowedWhileBooting(info)
- && !allowWhileBooting) {
- if (!mProcessesOnHold.contains(app)) {
- mProcessesOnHold.add(app);
- }
- if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
- "System not ready, putting on hold: " + app);
- checkTime(startTime, "startProcess: returning with proc on hold");
- return app;
- }
-
- checkTime(startTime, "startProcess: stepping in to startProcess");
- final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
- checkTime(startTime, "startProcess: done starting proc!");
- return success ? app : null;
- }
-
boolean isAllowedWhileBooting(ApplicationInfo ai) {
return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
}
- @GuardedBy("this")
- private final void startProcessLocked(ProcessRecord app,
- String hostingType, String hostingNameStr) {
- startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */);
- }
-
- @GuardedBy("this")
- private final boolean startProcessLocked(ProcessRecord app,
- String hostingType, String hostingNameStr, String abiOverride) {
- return startProcessLocked(app, hostingType, hostingNameStr,
- false /* disableHiddenApiChecks */, abiOverride);
- }
-
- /**
- * @return {@code true} if process start is successful, false otherwise.
- */
- @GuardedBy("this")
- private final boolean startProcessLocked(ProcessRecord app, String hostingType,
- String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
- if (app.pendingStart) {
- return true;
- }
- long startTime = SystemClock.elapsedRealtime();
- if (app.pid > 0 && app.pid != MY_PID) {
- checkTime(startTime, "startProcess: removing from pids map");
- synchronized (mPidsSelfLocked) {
- mPidsSelfLocked.remove(app.pid);
- mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- }
- checkTime(startTime, "startProcess: done removing from pids map");
- app.setPid(0);
- }
-
- if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
- "startProcessLocked removing on hold: " + app);
- mProcessesOnHold.remove(app);
-
- checkTime(startTime, "startProcess: starting to update cpu stats");
- updateCpuStats();
- checkTime(startTime, "startProcess: done updating cpu stats");
-
- try {
- try {
- final int userId = UserHandle.getUserId(app.uid);
- AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
-
- int uid = app.uid;
- int[] gids = null;
- int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
- if (!app.isolated) {
- int[] permGids = null;
- try {
- checkTime(startTime, "startProcess: getting gids from package manager");
- final IPackageManager pm = AppGlobals.getPackageManager();
- permGids = pm.getPackageGids(app.info.packageName,
- MATCH_DEBUG_TRIAGED_MISSING, app.userId);
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
- mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
- app.info.packageName);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
-
- /*
- * Add shared application and profile GIDs so applications can share some
- * resources like shared libraries and access user-wide resources
- */
- if (ArrayUtils.isEmpty(permGids)) {
- gids = new int[3];
- } else {
- gids = new int[permGids.length + 3];
- System.arraycopy(permGids, 0, gids, 3, permGids.length);
- }
- gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
- gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
- gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
-
- // Replace any invalid GIDs
- if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
- if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
- }
- checkTime(startTime, "startProcess: building args");
- if (mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
- uid = 0;
- }
- int runtimeFlags = 0;
- if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
- runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
- // Also turn on CheckJNI for debuggable apps. It's quite
- // awkward to turn on otherwise.
- runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
- }
- // Run the app in safe mode if its manifest requests so or the
- // system is booted in safe mode.
- if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
- mSafeMode == true) {
- runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
- }
- if ("1".equals(SystemProperties.get("debug.checkjni"))) {
- runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
- }
- String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
- if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
- runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
- }
- String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
- if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
- runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
- }
- if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
- runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
- }
- if ("1".equals(SystemProperties.get("debug.assert"))) {
- runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;
- }
- if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {
- // Enable all debug flags required by the native debugger.
- runtimeFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything
- runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info
- runtimeFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations
- mNativeDebuggingApp = null;
- }
-
- if (app.info.isPrivilegedApp() &&
- DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet())) {
- runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
- }
-
- if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
- app.info.maybeUpdateHiddenApiEnforcementPolicy(
- mHiddenApiBlacklist.getPolicyForPrePApps(),
- mHiddenApiBlacklist.getPolicyForPApps());
- @HiddenApiEnforcementPolicy int policy =
- app.info.getHiddenApiEnforcementPolicy();
- int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
- if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
- throw new IllegalStateException("Invalid API policy: " + policy);
- }
- runtimeFlags |= policyBits;
- }
-
- String invokeWith = null;
- if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- // Debuggable apps may include a wrapper script with their library directory.
- String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- try {
- if (new File(wrapperFileName).exists()) {
- invokeWith = "/system/bin/logwrapper " + wrapperFileName;
- }
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- }
- }
-
- String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
- if (requiredAbi == null) {
- requiredAbi = Build.SUPPORTED_ABIS[0];
- }
-
- String instructionSet = null;
- if (app.info.primaryCpuAbi != null) {
- instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
- }
-
- app.gids = gids;
- app.setRequiredAbi(requiredAbi);
- app.instructionSet = instructionSet;
-
- // the per-user SELinux context must be set
- if (TextUtils.isEmpty(app.info.seInfoUser)) {
- Slog.wtf(TAG, "SELinux tag not defined",
- new IllegalStateException("SELinux tag not defined for "
- + app.info.packageName + " (uid " + app.uid + ")"));
- }
- final String seInfo = app.info.seInfo
- + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
- // Start the process. It will either succeed and return a result containing
- // the PID of the new process, or else throw a RuntimeException.
- final String entryPoint = "android.app.ActivityThread";
-
- return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
- runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
- startTime);
- } catch (RuntimeException e) {
- Slog.e(TAG, "Failure starting process " + app.processName, e);
-
- // Something went very wrong while trying to start this process; one
- // common case is when the package is frozen due to an active
- // upgrade. To recover, clean up any active bookkeeping related to
- // starting this process. (We already invoked this method once when
- // the package was initially frozen through KILL_APPLICATION_MSG, so
- // it doesn't hurt to use it again.)
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
- false, true, false, false, app.userId, "start failure");
- return false;
- }
- }
-
- @GuardedBy("this")
- private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
- ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
- String seInfo, String requiredAbi, String instructionSet, String invokeWith,
- long startTime) {
- app.pendingStart = true;
- app.killedByAm = false;
- app.removed = false;
- app.killed = false;
- final long startSeq = app.startSeq = ++mProcStartSeqCounter;
- app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
- if (mConstants.FLAG_PROCESS_START_ASYNC) {
- if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
- "Posting procStart msg for " + app.toShortString());
- mProcStartHandler.post(() -> {
- try {
- synchronized (ActivityManagerService.this) {
- final String reason = isProcStartValidLocked(app, startSeq);
- if (reason != null) {
- Slog.w(TAG_PROCESSES, app + " not valid anymore,"
- + " don't start process, " + reason);
- app.pendingStart = false;
- return;
- }
- app.setUsingWrapper(invokeWith != null
- || SystemProperties.get("wrap." + app.processName) != null);
- mPendingStarts.put(startSeq, app);
- }
- final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
- app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
- requiredAbi, instructionSet, invokeWith, app.startTime);
- synchronized (ActivityManagerService.this) {
- handleProcessStartedLocked(app, startResult, startSeq);
- }
- } catch (RuntimeException e) {
- synchronized (ActivityManagerService.this) {
- Slog.e(TAG, "Failure starting process " + app.processName, e);
- mPendingStarts.remove(startSeq);
- app.pendingStart = false;
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
- false, false, true, false, false, app.userId, "start failure");
- }
- }
- });
- return true;
- } else {
- try {
- final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
- uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
- invokeWith, startTime);
- handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
- startSeq, false);
- } catch (RuntimeException e) {
- Slog.e(TAG, "Failure starting process " + app.processName, e);
- app.pendingStart = false;
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
- false, false, true, false, false, app.userId, "start failure");
- }
- return app.pid > 0;
- }
- }
-
- private ProcessStartResult startProcess(String hostingType, String entryPoint,
- ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
- String seInfo, String requiredAbi, String instructionSet, String invokeWith,
- long startTime) {
- try {
- final String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
- final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class)
- .getVisibleVolumesForUser(UserHandle.getUserId(uid));
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
- app.processName);
- checkTime(startTime, "startProcess: asking zygote to start proc");
- final ProcessStartResult startResult;
- if (hostingType.equals("webview_service")) {
- startResult = startWebView(entryPoint,
- app.processName, uid, uid, gids, runtimeFlags, mountExternal,
- app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, null, app.info.packageName,
- packageNames, visibleVolIds,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
- } else {
- startResult = Process.start(entryPoint,
- app.processName, uid, uid, gids, runtimeFlags, mountExternal,
- app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, invokeWith, app.info.packageName,
- packageNames, visibleVolIds,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
- }
- checkTime(startTime, "startProcess: returned from zygote!");
- return startResult;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- }
-
- @GuardedBy("this")
- private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
- StringBuilder sb = null;
- if (app.killedByAm) {
- if (sb == null) sb = new StringBuilder();
- sb.append("killedByAm=true;");
- }
- if (mProcessNames.get(app.processName, app.uid) != app) {
- if (sb == null) sb = new StringBuilder();
- sb.append("No entry in mProcessNames;");
- }
- if (!app.pendingStart) {
- if (sb == null) sb = new StringBuilder();
- sb.append("pendingStart=false;");
- }
- if (app.startSeq > expectedStartSeq) {
- if (sb == null) sb = new StringBuilder();
- sb.append("seq=" + app.startSeq + ",expected=" + expectedStartSeq + ";");
- }
- return sb == null ? null : sb.toString();
- }
-
- @GuardedBy("this")
- private boolean handleProcessStartedLocked(ProcessRecord pending,
- ProcessStartResult startResult, long expectedStartSeq) {
- // Indicates that this process start has been taken care of.
- if (mPendingStarts.get(expectedStartSeq) == null) {
- if (pending.pid == startResult.pid) {
- pending.setUsingWrapper(startResult.usingWrapper);
- // TODO: Update already existing clients of usingWrapper
- }
- return false;
- }
- return handleProcessStartedLocked(pending, startResult.pid, startResult.usingWrapper,
- expectedStartSeq, false);
- }
-
- @GuardedBy("this")
- private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
- long expectedStartSeq, boolean procAttached) {
- mPendingStarts.remove(expectedStartSeq);
- final String reason = isProcStartValidLocked(app, expectedStartSeq);
- if (reason != null) {
- Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" + pid
- + ", " + reason);
- app.pendingStart = false;
- Process.killProcessQuiet(pid);
- Process.killProcessGroup(app.uid, app.pid);
- return false;
- }
- mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
- checkTime(app.startTime, "startProcess: done updating battery stats");
-
- EventLog.writeEvent(EventLogTags.AM_PROC_START,
- UserHandle.getUserId(app.startUid), pid, app.startUid,
- app.processName, app.hostingType,
- app.hostingNameStr != null ? app.hostingNameStr : "");
-
- try {
- AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
- app.seInfo, app.info.sourceDir, pid);
- } catch (RemoteException ex) {
- // Ignore
- }
-
- if (app.isPersistent()) {
- Watchdog.getInstance().processStarted(app.processName, pid);
- }
-
- checkTime(app.startTime, "startProcess: building log message");
- StringBuilder buf = mStringBuilder;
- buf.setLength(0);
- buf.append("Start proc ");
- buf.append(pid);
- buf.append(':');
- buf.append(app.processName);
- buf.append('/');
- UserHandle.formatUid(buf, app.startUid);
- if (app.isolatedEntryPoint != null) {
- buf.append(" [");
- buf.append(app.isolatedEntryPoint);
- buf.append("]");
- }
- buf.append(" for ");
- buf.append(app.hostingType);
- if (app.hostingNameStr != null) {
- buf.append(" ");
- buf.append(app.hostingNameStr);
- }
- reportUidInfoMessageLocked(TAG, buf.toString(), app.startUid);
- app.setPid(pid);
- app.setUsingWrapper(usingWrapper);
- app.pendingStart = false;
- checkTime(app.startTime, "startProcess: starting to update pids map");
- ProcessRecord oldApp;
- synchronized (mPidsSelfLocked) {
- oldApp = mPidsSelfLocked.get(pid);
- }
- // If there is already an app occupying that pid that hasn't been cleaned up
- if (oldApp != null && !app.isolated) {
- // Clean up anything relating to this pid first
- Slog.w(TAG, "Reusing pid " + pid
- + " while app is still mapped to it");
- cleanUpApplicationRecordLocked(oldApp, false, false, -1,
- true /*replacingPid*/);
- }
- synchronized (mPidsSelfLocked) {
- this.mPidsSelfLocked.put(pid, app);
- if (!procAttached) {
- Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
- msg.obj = app;
- mHandler.sendMessageDelayed(msg, usingWrapper
- ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
- }
- }
- checkTime(app.startTime, "startProcess: done updating pids map");
- return true;
- }
-
void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
"updateUsageStats: comp=" + activity + "res=" + resumed);
@@ -3697,8 +2705,8 @@ public class ActivityManagerService extends IActivityManager.Stub
int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
synchronized (this) {
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- final ProcessRecord proc = mLruProcesses.get(i);
+ for (int i=mProcessList.mLruProcesses.size()-1; i>=0; i--) {
+ final ProcessRecord proc = mProcessList.mLruProcesses.get(i);
if (procState > proc.setProcState) {
if (proc.pkgList.containsKey(packageName) ||
(proc.pkgDeps != null && proc.pkgDeps.contains(packageName))) {
@@ -3992,9 +3000,35 @@ public class ActivityManagerService extends IActivityManager.Stub
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
- return mActivityTaskManager.startActivityAsUser(caller, callingPackage, intent,
- resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
- userId);
+ synchronized (this) {
+ /**
+ * Flags like {@link android.app.ActivityManager#START_FLAG_DEBUG} maybe be set on this
+ * call when called/invoked from the shell command. To avoid deadlock, we go ahead and
+ * acquire the AMS lock now since ATMS will need to synchronously call back into AMS
+ * later to modify process settings due to the flags.
+ * TODO(b/80414790): Investigate a better way of untangling this.
+ */
+ return mActivityTaskManager.startActivityAsUser(caller, callingPackage, intent,
+ resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo,
+ bOptions, userId);
+ }
+ }
+
+ WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
+ Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
+ int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
+ synchronized (this) {
+ /**
+ * Flags like {@link android.app.ActivityManager#START_FLAG_DEBUG} maybe be set on this
+ * call when called/invoked from the shell command. To avoid deadlock, we go ahead and
+ * acquire the AMS lock now since ATMS will need to synchronously call back into AMS
+ * later to modify process settings due to the flags.
+ * TODO(b/80414790): Investigate a better way of untangling this.
+ */
+ return mActivityTaskManager.startActivityAndWait(caller, callingPackage, intent,
+ resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo,
+ bOptions, userId);
+ }
}
@Override
@@ -4073,7 +3107,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* to the process.
*/
@GuardedBy("this")
- private final void handleAppDiedLocked(ProcessRecord app,
+ final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
@@ -4098,32 +3132,19 @@ public class ActivityManagerService extends IActivityManager.Stub
});
}
- private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
- final IBinder threadBinder = thread.asBinder();
- // Find the application record.
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- final ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
- return i;
- }
- }
- return -1;
- }
-
ProcessRecord getRecordForAppLocked(IApplicationThread thread) {
if (thread == null) {
return null;
}
- int appIndex = getLRURecordIndexForAppLocked(thread);
- if (appIndex >= 0) {
- return mLruProcesses.get(appIndex);
- }
+ ProcessRecord record = mProcessList.getLRURecordForAppLocked(thread);
+ if (record != null) return record;
// Validation: if it isn't in the LRU list, it shouldn't exist, but let's
// double-check that.
final IBinder threadBinder = thread.asBinder();
- final ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+ final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
+ mProcessList.mProcessNames.getMap();
for (int i = pmap.size()-1; i >= 0; i--) {
final SparseArray<ProcessRecord> procs = pmap.valueAt(i);
for (int j = procs.size()-1; j >= 0; j--) {
@@ -4143,17 +3164,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// If there are no longer any background processes running,
// and the app that died was not running instrumentation,
// then tell everyone we are now low on memory.
- boolean haveBg = false;
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null
- && rec.setProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
- haveBg = true;
- break;
- }
- }
-
- if (!haveBg) {
+ if (!mProcessList.haveBackgroundProcessLocked()) {
boolean doReport = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
if (doReport) {
long now = SystemClock.uptimeMillis();
@@ -4164,11 +3175,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
final ArrayList<ProcessMemInfo> memInfos
- = doReport ? new ArrayList<ProcessMemInfo>(mLruProcesses.size()) : null;
- EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
+ = doReport ? new ArrayList<ProcessMemInfo>(mProcessList.getLruSizeLocked())
+ : null;
+ EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mProcessList.getLruSizeLocked());
long now = SystemClock.uptimeMillis();
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord rec = mLruProcesses.get(i);
+ for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord rec = mProcessList.mLruProcesses.get(i);
if (rec == dyingProc || rec.thread == null) {
continue;
}
@@ -4225,7 +3237,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!fromBinderDied) {
killProcessQuiet(pid);
}
- killProcessGroup(app.uid, pid);
+ ProcessList.killProcessGroup(app.uid, pid);
app.killed = true;
}
@@ -4644,7 +3656,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
synchronized (this) {
- killPackageProcessesLocked(packageName, appId, targetUserId,
+ mProcessList.killPackageProcessesLocked(packageName, appId, targetUserId,
ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
}
}
@@ -4667,30 +3679,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- final ArrayList<ProcessRecord> procs = new ArrayList<>();
- final int NP = mProcessNames.getMap().size();
- for (int ip = 0; ip < NP; ip++) {
- final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia = 0; ia < NA; ia++) {
- final ProcessRecord app = apps.valueAt(ia);
- if (app.isPersistent()) {
- // We don't kill persistent processes.
- continue;
- }
- if (app.removed) {
- procs.add(app);
- } else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- app.removed = true;
- procs.add(app);
- }
- }
- }
-
- final int N = procs.size();
- for (int i = 0; i < N; i++) {
- removeProcessLocked(procs.get(i), false, true, "kill all background");
- }
+ mProcessList.killAllBackgroundProcessesLocked();
mAllowLowerMemLevel = true;
@@ -4724,27 +3713,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- final ArrayList<ProcessRecord> procs = new ArrayList<>();
- final int NP = mProcessNames.getMap().size();
- for (int ip = 0; ip < NP; ip++) {
- final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia = 0; ia < NA; ia++) {
- final ProcessRecord app = apps.valueAt(ia);
- if (app.removed) {
- procs.add(app);
- } else if ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
- && (maxProcState < 0 || app.setProcState > maxProcState)) {
- app.removed = true;
- procs.add(app);
- }
- }
- }
-
- final int N = procs.size();
- for (int i = 0; i < N; i++) {
- removeProcessLocked(procs.get(i), false, true, "kill all background except");
- }
+ mProcessList.killAllBackgroundProcessesExceptLocked(minTargetSdk, maxProcState);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -5042,81 +4011,6 @@ public class ActivityManagerService extends IActivityManager.Stub
null, false, false, MY_PID, SYSTEM_UID, UserHandle.getUserId(uid));
}
-
- @GuardedBy("this")
- private final boolean killPackageProcessesLocked(String packageName, int appId,
- int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
- boolean doit, boolean evenPersistent, String reason) {
- ArrayList<ProcessRecord> procs = new ArrayList<>();
-
- // Remove all processes this package may have touched: all with the
- // same UID (except for the system or root user), and all whose name
- // matches the package name.
- final int NP = mProcessNames.getMap().size();
- for (int ip=0; ip<NP; ip++) {
- SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia=0; ia<NA; ia++) {
- ProcessRecord app = apps.valueAt(ia);
- if (app.isPersistent() && !evenPersistent) {
- // we don't kill persistent processes
- continue;
- }
- if (app.removed) {
- if (doit) {
- procs.add(app);
- }
- continue;
- }
-
- // Skip process if it doesn't meet our oom adj requirement.
- if (app.setAdj < minOomAdj) {
- continue;
- }
-
- // If no package is specified, we call all processes under the
- // give user id.
- if (packageName == null) {
- if (userId != UserHandle.USER_ALL && app.userId != userId) {
- continue;
- }
- if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
- continue;
- }
- // Package has been specified, we want to hit all processes
- // that match it. We need to qualify this by the processes
- // that are running under the specified app and user ID.
- } else {
- final boolean isDep = app.pkgDeps != null
- && app.pkgDeps.contains(packageName);
- if (!isDep && UserHandle.getAppId(app.uid) != appId) {
- continue;
- }
- if (userId != UserHandle.USER_ALL && app.userId != userId) {
- continue;
- }
- if (!app.pkgList.containsKey(packageName) && !isDep) {
- continue;
- }
- }
-
- // Process has passed all conditions, kill it!
- if (!doit) {
- return true;
- }
- app.removed = true;
- procs.add(app);
- }
- }
-
- int N = procs.size();
- for (int i=0; i<N; i++) {
- removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
- }
- updateOomAdjLocked();
- return N > 0;
- }
-
private void cleanupDisabledPackageComponentsLocked(
String packageName, int userId, boolean killProcess, String[] changedClasses) {
@@ -5237,7 +4131,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mAppErrors.resetProcessCrashTimeLocked(packageName == null, appId, userId);
}
- boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
+ boolean didSomething = mProcessList.killPackageProcessesLocked(packageName, appId, userId,
ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent,
packageName == null ? ("stop user " + userId) : ("stop " + packageName));
@@ -5299,128 +4193,10 @@ public class ActivityManagerService extends IActivityManager.Stub
return didSomething;
}
- private final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
- return removeProcessNameLocked(name, uid, null);
- }
-
- private final ProcessRecord removeProcessNameLocked(final String name, final int uid,
- final ProcessRecord expecting) {
- ProcessRecord old = mProcessNames.get(name, uid);
- // Only actually remove when the currently recorded value matches the
- // record that we expected; if it doesn't match then we raced with a
- // newly created process and we don't want to destroy the new one.
- if ((expecting == null) || (old == expecting)) {
- mProcessNames.remove(name, uid);
- }
- if (old != null && old.uidRecord != null) {
- old.uidRecord.numProcs--;
- if (old.uidRecord.numProcs == 0) {
- // No more processes using this uid, tell clients it is gone.
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "No more processes in " + old.uidRecord);
- enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
- EventLogTags.writeAmUidStopped(uid);
- mActiveUids.remove(uid);
- noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
- }
- old.uidRecord = null;
- }
- mIsolatedProcesses.remove(uid);
- return old;
- }
-
- private final void addProcessNameLocked(ProcessRecord proc) {
- // We shouldn't already have a process under this name, but just in case we
- // need to clean up whatever may be there now.
- ProcessRecord old = removeProcessNameLocked(proc.processName, proc.uid);
- if (old == proc && proc.isPersistent()) {
- // We are re-adding a persistent process. Whatevs! Just leave it there.
- Slog.w(TAG, "Re-adding persistent process " + proc);
- } else if (old != null) {
- Slog.wtf(TAG, "Already have existing proc " + old + " when adding " + proc);
- }
- UidRecord uidRec = mActiveUids.get(proc.uid);
- if (uidRec == null) {
- uidRec = new UidRecord(proc.uid);
- // This is the first appearance of the uid, report it now!
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "Creating new process uid: " + uidRec);
- if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0
- || mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) {
- uidRec.setWhitelist = uidRec.curWhitelist = true;
- }
- uidRec.updateHasInternetPermission();
- mActiveUids.put(proc.uid, uidRec);
- EventLogTags.writeAmUidRunning(uidRec.uid);
- noteUidProcessState(uidRec.uid, uidRec.curProcState);
- }
- proc.uidRecord = uidRec;
-
- // Reset render thread tid if it was already set, so new process can set it again.
- proc.renderThreadTid = 0;
- uidRec.numProcs++;
- mProcessNames.put(proc.processName, proc.uid, proc);
- if (proc.isolated) {
- mIsolatedProcesses.put(proc.uid, proc);
- }
- }
-
- @GuardedBy("this")
- boolean removeProcessLocked(ProcessRecord app,
- boolean callerWillRestart, boolean allowRestart, String reason) {
- final String name = app.processName;
- final int uid = app.uid;
- if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES,
- "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")");
-
- ProcessRecord old = mProcessNames.get(name, uid);
- if (old != app) {
- // This process is no longer active, so nothing to do.
- Slog.w(TAG, "Ignoring remove of inactive process: " + app);
- return false;
- }
- removeProcessNameLocked(name, uid);
- mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
-
- boolean needRestart = false;
- if ((app.pid > 0 && app.pid != MY_PID) || (app.pid == 0 && app.pendingStart)) {
- int pid = app.pid;
- if (pid > 0) {
- synchronized (mPidsSelfLocked) {
- mPidsSelfLocked.remove(pid);
- mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- }
- mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
- if (app.isolated) {
- mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
- getPackageManagerInternalLocked().removeIsolatedUid(app.uid);
- }
- }
- boolean willRestart = false;
- if (app.isPersistent() && !app.isolated) {
- if (!callerWillRestart) {
- willRestart = true;
- } else {
- needRestart = true;
- }
- }
- app.kill(reason, true);
- handleAppDiedLocked(app, willRestart, allowRestart);
- if (willRestart) {
- removeLruProcessLocked(app);
- addAppLocked(app.info, null, false, null /* ABI override */);
- }
- } else {
- mRemovedProcesses.add(app);
- }
-
- return needRestart;
- }
-
@GuardedBy("this")
private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
cleanupAppInLaunchingProvidersLocked(app, true);
- removeProcessLocked(app, false, true, "timeout publishing content providers");
+ mProcessList.removeProcessLocked(app, false, true, "timeout publishing content providers");
}
private final void processStartTimedOutLocked(ProcessRecord app) {
@@ -5438,7 +4214,7 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.w(TAG, "Process " + app + " failed to attach");
EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, app.userId,
pid, app.uid, app.processName);
- removeProcessNameLocked(app.processName, app.uid);
+ mProcessList.removeProcessNameLocked(app.processName, app.uid);
mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
// Take care of any launching providers waiting for this process.
@@ -5494,9 +4270,10 @@ public class ActivityManagerService extends IActivityManager.Stub
// It's possible that process called attachApplication before we got a chance to
// update the internal state.
if (app == null && startSeq > 0) {
- final ProcessRecord pending = mPendingStarts.get(startSeq);
+ final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
if (pending != null && pending.startUid == callingUid
- && handleProcessStartedLocked(pending, pid, pending.isUsingWrapper(),
+ && mProcessList.handleProcessStartedLocked(pending, pid, pending
+ .isUsingWrapper(),
startSeq, true)) {
app = pending;
}
@@ -5538,7 +4315,7 @@ public class ActivityManagerService extends IActivityManager.Stub
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
- startProcessLocked(app, "link fail", processName);
+ mProcessList.startProcessLocked(app, "link fail", processName);
return false;
}
@@ -5749,7 +4526,7 @@ public class ActivityManagerService extends IActivityManager.Stub
profilerInfo = null;
}
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
- updateLruProcessLocked(app, false, null);
+ mProcessList.updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
@@ -5760,7 +4537,7 @@ public class ActivityManagerService extends IActivityManager.Stub
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
- startProcessLocked(app, "bind fail", processName);
+ mProcessList.startProcessLocked(app, "bind fail", processName);
return false;
}
@@ -5933,7 +4710,7 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int ip=0; ip<NP; ip++) {
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "Starting process on hold: "
+ procs.get(ip));
- startProcessLocked(procs.get(ip), "on-hold", null);
+ mProcessList.startProcessLocked(procs.get(ip), "on-hold", null);
}
}
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
@@ -6890,19 +5667,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
- final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
- final long cachedAppMem = mProcessList.getMemLevel(ProcessList.CACHED_APP_MIN_ADJ);
- outInfo.availMem = getFreeMemory();
- outInfo.totalMem = getTotalMemory();
- outInfo.threshold = homeAppMem;
- outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
- outInfo.hiddenAppThreshold = cachedAppMem;
- outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
- ProcessList.SERVICE_ADJ);
- outInfo.visibleAppThreshold = mProcessList.getMemLevel(
- ProcessList.VISIBLE_APP_ADJ);
- outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
- ProcessList.FOREGROUND_APP_ADJ);
+ mProcessList.getMemoryInfo(outInfo);
}
// =========================================================
@@ -7338,7 +6103,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return false;
}
- private void checkTime(long startTime, String where) {
+ void checkTime(long startTime, String where) {
long now = SystemClock.uptimeMillis();
if ((now-startTime) > 50) {
// If we are taking more than 50ms, log about it.
@@ -7497,7 +6262,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// back up on the LRU list. This is good because
// content providers are often expensive to start.
checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
- updateLruProcessLocked(cpr.proc, false, null);
+ mProcessList.updateLruProcessLocked(cpr.proc, false, null);
checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
}
}
@@ -8143,7 +6908,7 @@ public class ActivityManagerService extends IActivityManager.Stub
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
- ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
+ ProcessRecord app = mProcessList.mProcessNames.get("system", SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
@@ -8205,9 +6970,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final int matchFlags = GET_PROVIDERS | MATCH_DIRECT_BOOT_UNAWARE;
synchronized (this) {
- final int NP = mProcessNames.getMap().size();
+ final int NP = mProcessList.mProcessNames.getMap().size();
for (int ip = 0; ip < NP; ip++) {
- final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final SparseArray<ProcessRecord> apps = mProcessList.mProcessNames.getMap().valueAt
+ (ip);
final int NA = apps.size();
for (int ia = 0; ia < NA; ia++) {
final ProcessRecord app = apps.valueAt(ia);
@@ -8313,67 +7079,6 @@ public class ActivityManagerService extends IActivityManager.Stub
// GLOBAL MANAGEMENT
// =========================================================
- @GuardedBy("this")
- final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
- boolean isolated, int isolatedUid) {
- String proc = customProcess != null ? customProcess : info.processName;
- final int userId = UserHandle.getUserId(info.uid);
- int uid = info.uid;
- if (isolated) {
- if (isolatedUid == 0) {
- int stepsLeft = LAST_ISOLATED_UID - FIRST_ISOLATED_UID + 1;
- while (true) {
- if (mNextIsolatedProcessUid < FIRST_ISOLATED_UID
- || mNextIsolatedProcessUid > LAST_ISOLATED_UID) {
- mNextIsolatedProcessUid = FIRST_ISOLATED_UID;
- }
- uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
- mNextIsolatedProcessUid++;
- if (mIsolatedProcesses.indexOfKey(uid) < 0) {
- // No process for this uid, use it.
- break;
- }
- stepsLeft--;
- if (stepsLeft <= 0) {
- return null;
- }
- }
- } else {
- // Special case for startIsolatedProcess (internal only), where
- // the uid of the isolated process is specified by the caller.
- uid = isolatedUid;
- }
- getPackageManagerInternalLocked().addIsolatedUid(uid, info.uid);
-
- // Register the isolated UID with this application so BatteryStats knows to
- // attribute resource usage to the application.
- //
- // NOTE: This is done here before addProcessNameLocked, which will tell BatteryStats
- // about the process state of the isolated UID *before* it is registered with the
- // owning application.
- mBatteryStatsService.addIsolatedUid(uid, info.uid);
- StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
- StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
- }
- final ProcessRecord r = new ProcessRecord(this, info, proc, uid, getGlobalConfiguration());
- if (!mBooted && !mBooting
- && userId == UserHandle.USER_SYSTEM
- && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
- // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
- r.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
- r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
- r.setPersistent(true);
- r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
- }
- if (isolated && isolatedUid != 0) {
- // Special case for startIsolatedProcess (internal only) - assume the process
- // is required by the system server to prevent it being killed.
- r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
- }
- addProcessNameLocked(r);
- return r;
- }
-
private boolean uidOnBackgroundWhitelist(final int uid) {
final int appId = UserHandle.getAppId(uid);
final int[] whitelist = mBackgroundAppIdWhitelist;
@@ -8434,6 +7139,7 @@ public class ActivityManagerService extends IActivityManager.Stub
abiOverride);
}
+ // TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, String abiOverride) {
@@ -8446,8 +7152,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (app == null) {
- app = newProcessRecordLocked(info, customProcess, isolated, 0);
- updateLruProcessLocked(app, false, null);
+ app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0);
+ mProcessList.updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
@@ -8467,7 +7173,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
- startProcessLocked(app, "added application",
+ mProcessList.startProcessLocked(app, "added application",
customProcess != null ? customProcess : app.processName, disableHiddenApiChecks,
abiOverride);
}
@@ -9331,7 +8037,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
try {
- killPackageProcessesLocked(null, appId, userId,
+ mProcessList.killPackageProcessesLocked(null, appId, userId,
ProcessList.PERSISTENT_PROC_ADJ, false, true, true, true,
reason != null ? reason : "kill uid");
} finally {
@@ -9481,8 +8187,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final long memoryGrowthThreshold =
Math.max(totalMemoryInKb / 100, MINIMUM_MEMORY_GROWTH_THRESHOLD);
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord proc = mLruProcesses.get(i);
+ for (int i = mProcessList.mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+ ProcessRecord proc = mProcessList.mLruProcesses.get(i);
if (proc.notCachedSinceIdle) {
if (proc.setProcState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
&& proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
@@ -9612,7 +8318,7 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
- removeProcessLocked(proc, true, false, "system update done");
+ mProcessList.removeProcessLocked(proc, true, false, "system update done");
}
}
@@ -9999,22 +8705,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (this) {
- final int NP = mProcessNames.getMap().size();
- for (int ip=0; ip<NP; ip++) {
- SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia=0; ia<NA; ia++) {
- ProcessRecord p = apps.valueAt(ia);
- if (p.thread != null && p.thread.asBinder() == app) {
- return p;
- }
- }
- }
-
- Slog.w(TAG, "Can't find mystery application for " + reason
- + " from pid=" + Binder.getCallingPid()
- + " uid=" + Binder.getCallingUid() + ": " + app);
- return null;
+ return mProcessList.findAppProcessLocked(app, reason);
}
}
@@ -10230,8 +8921,8 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
// iterate across all processes
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ for (int i=mProcessList.mLruProcesses.size()-1; i>=0; i--) {
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!allUsers && app.userId != userId) {
continue;
}
@@ -10264,44 +8955,6 @@ public class ActivityManagerService extends IActivityManager.Stub
return errList;
}
- static int procStateToImportance(int procState, int memAdj,
- ActivityManager.RunningAppProcessInfo currApp,
- int clientTargetSdk) {
- int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk(
- procState, clientTargetSdk);
- if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
- currApp.lru = memAdj;
- } else {
- currApp.lru = 0;
- }
- return imp;
- }
-
- @GuardedBy("this")
- private void fillInProcMemInfoLocked(ProcessRecord app,
- ActivityManager.RunningAppProcessInfo outInfo,
- int clientTargetSdk) {
- outInfo.pid = app.pid;
- outInfo.uid = app.info.uid;
- if (mAtmInternal.isHeavyWeightProcess(app.getWindowProcessController())) {
- outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
- }
- if (app.isPersistent()) {
- outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
- }
- if (app.hasActivities()) {
- outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
- }
- outInfo.lastTrimLevel = app.trimMemoryLevel;
- int adj = app.curAdj;
- int procState = app.getCurProcState();
- outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk);
- outInfo.importanceReasonCode = app.adjTypeCode;
- outInfo.processState = app.getCurProcState();
- outInfo.isFocused = (app == getTopAppLocked());
- outInfo.lastActivityTime = app.lastActivityTime;
- }
-
@Override
public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
enforceNotIsolatedCaller("getRunningAppProcesses");
@@ -10309,8 +8962,6 @@ public class ActivityManagerService extends IActivityManager.Stub
final int callingUid = Binder.getCallingUid();
final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
- // Lazy instantiation of list
- List<ActivityManager.RunningAppProcessInfo> runList = null;
final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
callingUid) == PackageManager.PERMISSION_GRANTED;
final int userId = UserHandle.getUserId(callingUid);
@@ -10319,44 +8970,9 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
// Iterate across all processes
- for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- if ((!allUsers && app.userId != userId)
- || (!allUids && app.uid != callingUid)) {
- continue;
- }
- if ((app.thread != null) && (!app.isCrashing() && !app.isNotResponding())) {
- // Generate process state info for running application
- ActivityManager.RunningAppProcessInfo currApp =
- new ActivityManager.RunningAppProcessInfo(app.processName,
- app.pid, app.getPackageList());
- fillInProcMemInfoLocked(app, currApp, clientTargetSdk);
- if (app.adjSource instanceof ProcessRecord) {
- currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
- currApp.importanceReasonImportance =
- ActivityManager.RunningAppProcessInfo.procStateToImportance(
- app.adjSourceProcState);
- } else if (app.adjSource instanceof ActivityServiceConnectionsHolder) {
- ActivityServiceConnectionsHolder r =
- (ActivityServiceConnectionsHolder) app.adjSource;
- final int pid = r.getActivityPid();
- if (pid != -1) {
- currApp.importanceReasonPid = pid;
- }
- }
- if (app.adjTarget instanceof ComponentName) {
- currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
- }
- //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
- // + " lru=" + currApp.lru);
- if (runList == null) {
- runList = new ArrayList<>();
- }
- runList.add(currApp);
- }
- }
+ return mProcessList.getRunningAppProcessesLocked(allUsers, userId, allUids,
+ callingUid, clientTargetSdk);
}
- return runList;
}
@Override
@@ -10403,7 +9019,7 @@ public class ActivityManagerService extends IActivityManager.Stub
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
if (proc != null) {
- fillInProcMemInfoLocked(proc, outState, clientTargetSdk);
+ mProcessList.fillInProcMemInfoLocked(proc, outState, clientTargetSdk);
}
}
}
@@ -11020,6 +9636,7 @@ public class ActivityManagerService extends IActivityManager.Stub
"Counts of Binder Proxies held by SYSTEM");
}
+ // TODO: Move to ProcessList?
@GuardedBy("this")
void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage, int dumpAppId) {
@@ -11029,9 +9646,9 @@ public class ActivityManagerService extends IActivityManager.Stub
pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
if (dumpAll) {
- final int NP = mProcessNames.getMap().size();
+ final int NP = mProcessList.mProcessNames.getMap().size();
for (int ip=0; ip<NP; ip++) {
- SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
+ SparseArray<ProcessRecord> procs = mProcessList.mProcessNames.getMap().valueAt(ip);
final int NA = procs.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord r = procs.valueAt(ia);
@@ -11053,10 +9670,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- if (mIsolatedProcesses.size() > 0) {
+ if (mProcessList.mIsolatedProcesses.size() > 0) {
boolean printed = false;
- for (int i=0; i<mIsolatedProcesses.size(); i++) {
- ProcessRecord r = mIsolatedProcesses.valueAt(i);
+ for (int i=0; i<mProcessList.mIsolatedProcesses.size(); i++) {
+ ProcessRecord r = mProcessList.mIsolatedProcesses.valueAt(i);
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
continue;
}
@@ -11109,17 +9726,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- if (mLruProcesses.size() > 0) {
+ if (mProcessList.getLruSizeLocked() > 0) {
if (needSep) {
pw.println();
}
- pw.print(" Process LRU list (sorted by oom_adj, "); pw.print(mLruProcesses.size());
- pw.print(" total, non-act at ");
- pw.print(mLruProcesses.size()-mLruProcessActivityStart);
- pw.print(", non-svc at ");
- pw.print(mLruProcesses.size()-mLruProcessServiceStart);
- pw.println("):");
- dumpProcessOomList(pw, this, mLruProcesses, " ", "Proc", "PERS", false, dumpPackage);
+ mProcessList.dumpLruListHeaderLocked(pw);
+ dumpProcessOomList(pw, this, mProcessList.mLruProcesses, " ", "Proc", "PERS", false,
+ dumpPackage);
needSep = true;
}
@@ -11173,11 +9786,11 @@ public class ActivityManagerService extends IActivityManager.Stub
"Starting Norm", "Restarting PERS", dumpPackage);
}
- if (mRemovedProcesses.size() > 0) {
+ if (mProcessList.mRemovedProcesses.size() > 0) {
if (needSep) pw.println();
needSep = true;
pw.println(" Processes that are being removed:");
- dumpProcessList(pw, this, mRemovedProcesses, " ",
+ dumpProcessList(pw, this, mProcessList.mRemovedProcesses, " ",
"Removed Norm", "Removed PERS", dumpPackage);
}
@@ -11202,12 +9815,13 @@ public class ActivityManagerService extends IActivityManager.Stub
needSep = mAtmInternal.dumpForProcesses(fd, pw, dumpAll, dumpPackage, dumpAppId, needSep,
mTestPssMode, mWakefulness);
- if (dumpAll && mPendingStarts.size() > 0) {
+ if (dumpAll && mProcessList.mPendingStarts.size() > 0) {
if (needSep) pw.println();
needSep = true;
pw.println(" mPendingStarts: ");
- for (int i = 0, len = mPendingStarts.size(); i < len; ++i ) {
- pw.println(" " + mPendingStarts.keyAt(i) + ": " + mPendingStarts.valueAt(i));
+ for (int i = 0, len = mProcessList.mPendingStarts.size(); i < len; ++i ) {
+ pw.println(" " + mProcessList.mPendingStarts.keyAt(i) + ": "
+ + mProcessList.mPendingStarts.valueAt(i));
}
}
if (dumpAll) {
@@ -11360,9 +9974,9 @@ public class ActivityManagerService extends IActivityManager.Stub
pw.print(" mLastPowerCheckUptime=");
TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
pw.println("");
- pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
+ pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.mLruSeq);
pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
- + " (" + mLruProcesses.size() + " total)"
+ + " (" + mProcessList.getLruSizeLocked() + " total)"
+ " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
+ " mNumServiceProcs=" + mNumServiceProcs
+ " mNewNumServiceProcs=" + mNewNumServiceProcs);
@@ -11408,9 +10022,9 @@ public class ActivityManagerService extends IActivityManager.Stub
void writeProcessesToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
int numPers = 0;
- final int NP = mProcessNames.getMap().size();
+ final int NP = mProcessList.mProcessNames.getMap().size();
for (int ip=0; ip<NP; ip++) {
- SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
+ SparseArray<ProcessRecord> procs = mProcessList.mProcessNames.getMap().valueAt(ip);
final int NA = procs.size();
for (int ia = 0; ia<NA; ia++) {
ProcessRecord r = procs.valueAt(ia);
@@ -11424,8 +10038,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- for (int i=0; i<mIsolatedProcesses.size(); i++) {
- ProcessRecord r = mIsolatedProcesses.valueAt(i);
+ for (int i=0; i<mProcessList.mIsolatedProcesses.size(); i++) {
+ ProcessRecord r = mProcessList.mIsolatedProcesses.valueAt(i);
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
continue;
}
@@ -11458,14 +10072,17 @@ public class ActivityManagerService extends IActivityManager.Stub
uidRec.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VALIDATE_UIDS);
}
- if (mLruProcesses.size() > 0) {
+ if (mProcessList.getLruSizeLocked() > 0) {
long lruToken = proto.start(ActivityManagerServiceDumpProcessesProto.LRU_PROCS);
- int total = mLruProcesses.size();
+ int total = mProcessList.getLruSizeLocked();
proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.SIZE, total);
- proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_ACT_AT, total-mLruProcessActivityStart);
- proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_SVC_AT, total-mLruProcessServiceStart);
- writeProcessOomListToProto(proto, ActivityManagerServiceDumpProcessesProto.LruProcesses.LIST, this,
- mLruProcesses,false, dumpPackage);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_ACT_AT,
+ total - mProcessList.mLruProcessActivityStart);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_SVC_AT,
+ total - mProcessList.mLruProcessServiceStart);
+ writeProcessOomListToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.LruProcesses.LIST, this,
+ mProcessList.mLruProcesses,false, dumpPackage);
proto.end(lruToken);
}
@@ -11476,7 +10093,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!r.pkgList.containsKey(dumpPackage)) {
continue;
}
- r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PIDS_SELF_LOCKED);
+ r.writeToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.PIDS_SELF_LOCKED);
}
}
}
@@ -11490,7 +10108,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|| !r.pkgList.containsKey(dumpPackage))) {
continue;
}
- it.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.IMPORTANT_PROCS);
+ it.writeToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.IMPORTANT_PROCS);
}
}
}
@@ -11500,11 +10119,12 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
continue;
}
- r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PERSISTENT_STARTING_PROCS);
+ r.writeToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.PERSISTENT_STARTING_PROCS);
}
- for (int i=0; i<mRemovedProcesses.size(); i++) {
- ProcessRecord r = mRemovedProcesses.get(i);
+ for (int i = 0; i < mProcessList.mRemovedProcesses.size(); i++) {
+ ProcessRecord r = mProcessList.mRemovedProcesses.get(i);
if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
continue;
}
@@ -11638,7 +10258,7 @@ public class ActivityManagerService extends IActivityManager.Stub
proto.write(ActivityManagerServiceDumpProcessesProto.BOOT_ANIMATION_COMPLETE, mBootAnimationComplete);
proto.write(ActivityManagerServiceDumpProcessesProto.LAST_POWER_CHECK_UPTIME_MS, mLastPowerCheckUptime);
proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq);
- proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mLruSeq);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.mLruSeq);
proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS, mNumNonCachedProcs);
proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs);
proto.write(ActivityManagerServiceDumpProcessesProto.NEW_NUM_SERVICE_PROCS, mNewNumServiceProcs);
@@ -11719,7 +10339,7 @@ public class ActivityManagerService extends IActivityManager.Stub
int opti, boolean dumpAll) {
boolean needSep = false;
- if (mLruProcesses.size() > 0) {
+ if (mProcessList.getLruSizeLocked() > 0) {
if (needSep) pw.println();
needSep = true;
pw.println(" OOM levels:");
@@ -11739,13 +10359,16 @@ public class ActivityManagerService extends IActivityManager.Stub
printOomLevel(pw, "CACHED_APP_MAX_ADJ", ProcessList.CACHED_APP_MAX_ADJ);
if (needSep) pw.println();
- pw.print(" Process OOM control ("); pw.print(mLruProcesses.size());
+ pw.print(" Process OOM control ("); pw.print(mProcessList.getLruSizeLocked());
pw.print(" total, non-act at ");
- pw.print(mLruProcesses.size()-mLruProcessActivityStart);
+ pw.print(mProcessList.getLruSizeLocked()
+ - mProcessList.mLruProcessActivityStart);
pw.print(", non-svc at ");
- pw.print(mLruProcesses.size()-mLruProcessServiceStart);
+ pw.print(mProcessList.getLruSizeLocked()
+ - mProcessList.mLruProcessServiceStart);
pw.println("):");
- dumpProcessOomList(pw, this, mLruProcesses, " ", "Proc", "PERS", true, null);
+ dumpProcessOomList(pw, this, mProcessList.mLruProcesses, " ", "Proc", "PERS", true,
+ null);
needSep = true;
}
@@ -12380,35 +11003,9 @@ public class ActivityManagerService extends IActivityManager.Stub
ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, boolean allPkgs,
String[] args) {
- ArrayList<ProcessRecord> procs;
synchronized (this) {
- if (args != null && args.length > start
- && args[start].charAt(0) != '-') {
- procs = new ArrayList<ProcessRecord>();
- int pid = -1;
- try {
- pid = Integer.parseInt(args[start]);
- } catch (NumberFormatException e) {
- }
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord proc = mLruProcesses.get(i);
- if (proc.pid > 0 && proc.pid == pid) {
- procs.add(proc);
- } else if (allPkgs && proc.pkgList != null
- && proc.pkgList.containsKey(args[start])) {
- procs.add(proc);
- } else if (proc.processName.equals(args[start])) {
- procs.add(proc);
- }
- }
- if (procs.size() <= 0) {
- return null;
- }
- } else {
- procs = new ArrayList<ProcessRecord>(mLruProcesses);
- }
+ return mProcessList.collectProcessesLocked(start, allPkgs, args);
}
- return procs;
}
final void dumpGraphicsHardwareUsage(FileDescriptor fd,
@@ -14103,7 +12700,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* app that was passed in must remain on the process lists.
*/
@GuardedBy("this")
- private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
+ final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
if (index >= 0) {
removeLruProcessLocked(app);
@@ -14243,7 +12840,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
- removeProcessNameLocked(app.processName, app.uid, app);
+ mProcessList.removeProcessNameLocked(app.processName, app.uid, app);
}
mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
} else if (!app.removed) {
@@ -14267,9 +12864,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (index < 0) {
ProcessList.remove(app.pid);
}
- addProcessNameLocked(app);
+ mProcessList.addProcessNameLocked(app);
app.pendingStart = false;
- startProcessLocked(app, "restart", app.processName);
+ mProcessList.startProcessLocked(app, "restart", app.processName);
return true;
} else if (app.pid > 0 && app.pid != MY_PID) {
// Goodbye!
@@ -15006,15 +13603,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private final void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
- try {
- r.thread.dispatchPackageBroadcast(cmd, packages);
- } catch (RemoteException ex) {
- }
- }
- }
+ mProcessList.sendPackageBroadcastLocked(cmd, packages, userId);
}
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
@@ -15423,8 +14012,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else {
if (killProcess) {
- killPackageProcessesLocked(ssp, UserHandle.getAppId(
- intent.getIntExtra(Intent.EXTRA_UID, -1)),
+ final int extraUid = intent.getIntExtra(Intent.EXTRA_UID,
+ -1);
+ mProcessList.killPackageProcessesLocked(ssp,
+ UserHandle.getAppId(extraUid),
userId, ProcessList.INVALID_ADJ,
false, true, true, false, "change " + ssp);
}
@@ -16413,7 +15004,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- private void noteUidProcessState(final int uid, final int state) {
+ void noteUidProcessState(final int uid, final int state) {
mBatteryStatsService.noteUidProcessState(uid, state);
mAppOpsService.updateUidProcState(uid, state);
if (mTrackingAssociations) {
@@ -16445,6 +15036,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
new ComputeOomAdjWindowCallback();
+ /** These methods are called inline during computeOomAdjLocked(), on the same thread */
private final class ComputeOomAdjWindowCallback
implements WindowProcessController.ComputeOomAdjCallback {
@@ -17626,10 +16218,10 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = mPendingPssProcesses.size() - 1; i >= 0; i--) {
ProcessList.abortNextPssTime(mPendingPssProcesses.get(i).procStateMemTracker);;
}
- mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
+ mPendingPssProcesses.ensureCapacity(mProcessList.getLruSizeLocked());
mPendingPssProcesses.clear();
- for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ for (int i = mProcessList.getLruSizeLocked() - 1; i >= 0; i--) {
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (app.thread == null
|| app.getCurProcState() == ActivityManager.PROCESS_STATE_NONEXISTENT) {
continue;
@@ -17805,10 +16397,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - mLastPowerCheckUptime;
mLastPowerCheckUptime = curUptime;
- int i = mLruProcesses.size();
+ int i = mProcessList.mLruProcesses.size();
while (i > 0) {
i--;
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
if (app.lastCpuTime <= 0) {
continue;
@@ -18358,7 +16950,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update
// the logic there and in mBatteryStatsService to make them aware of multiple resumed activities
- private ProcessRecord getTopAppLocked() {
+ ProcessRecord getTopAppLocked() {
final WindowProcessController wpc = mAtmInternal != null ? mAtmInternal.getTopApp() : null;
final ProcessRecord r = wpc != null ? (ProcessRecord) wpc.mOwner : null;
String pkg;
@@ -18432,7 +17024,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final long now = SystemClock.uptimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
- final int N = mLruProcesses.size();
+ final int N = mProcessList.getLruSizeLocked();
// Reset state in all uid records.
for (int i=mActiveUids.size()-1; i>=0; i--) {
@@ -18493,11 +17085,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// need to reset cycle state before calling computeOomAdjLocked because of service connections
for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
app.containsCycle = false;
}
for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
@@ -18572,7 +17164,7 @@ public class ActivityManagerService extends IActivityManager.Stub
retryCycles = false;
for (int i=0; i<N; i++) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
app.adjSeq--;
app.completedAdjSeq--;
@@ -18580,7 +17172,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
for (int i=0; i<N; i++) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now)) {
@@ -18591,7 +17183,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
applyOomAdjLocked(app, true, now, nowElapsed);
@@ -18684,9 +17276,9 @@ public class ActivityManagerService extends IActivityManager.Stub
// has gone down since last time.
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+ " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
- + " numProcs=" + mLruProcesses.size() + " last=" + mLastNumProcesses);
+ + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
if (memFactor > mLastMemoryLevel) {
- if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
+ if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
memFactor = mLastMemoryLevel;
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
}
@@ -18696,7 +17288,7 @@ public class ActivityManagerService extends IActivityManager.Stub
StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
}
mLastMemoryLevel = memFactor;
- mLastNumProcesses = mLruProcesses.size();
+ mLastNumProcesses = mProcessList.getLruSizeLocked();
boolean allChanged = mProcessStats.setMemFactorLocked(
memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
@@ -18724,7 +17316,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (factor < minFactor) factor = minFactor;
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
@@ -18802,7 +17394,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mLowRamStartTime = 0;
}
for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
@@ -19066,7 +17658,7 @@ public class ActivityManagerService extends IActivityManager.Stub
continue;
}
synchronized (uidRec.networkStateLock) {
- uidRec.curProcStateSeq = ++mProcStateSeqCounter;
+ uidRec.curProcStateSeq = ++mProcessList.mProcStateSeqCounter; // TODO: use method
if (blockState == NETWORK_STATE_BLOCK) {
if (blockingUids == null) {
blockingUids = new ArrayList<>();
@@ -19089,8 +17681,8 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
- for (int i = mLruProcesses.size() - 1; i >= 0; --i) {
- final ProcessRecord app = mLruProcesses.get(i);
+ for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; --i) {
+ final ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!blockingUids.contains(app.uid)) {
continue;
}
@@ -19288,8 +17880,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final void trimApplicationsLocked() {
// First remove any unused application processes whose package
// has been removed.
- for (int i=mRemovedProcesses.size()-1; i>=0; i--) {
- final ProcessRecord app = mRemovedProcesses.get(i);
+ for (int i = mProcessList.mRemovedProcesses.size() - 1; i >= 0; i--) {
+ final ProcessRecord app = mProcessList.mRemovedProcesses.get(i);
if (!app.hasActivitiesOrRecentTasks()
&& app.curReceivers.isEmpty() && app.services.size() == 0) {
Slog.i(
@@ -19307,7 +17899,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
- mRemovedProcesses.remove(i);
+ mProcessList.mRemovedProcesses.remove(i);
if (app.isPersistent()) {
addAppLocked(app.info, null, false, null /* ABI override */);
@@ -19333,8 +17925,8 @@ public class ActivityManagerService extends IActivityManager.Stub
+ android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
}
- for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mLruProcesses.get(i);
+ for (int i = mProcessList.mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+ ProcessRecord r = mProcessList.mLruProcesses.get(i);
if (r.thread != null && r.isPersistent()) {
sendSignal(r.pid, sig);
}
@@ -19461,7 +18053,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (proc == null) {
ArrayMap<String, SparseArray<ProcessRecord>> all
- = mProcessNames.getMap();
+ = mProcessList.mProcessNames.getMap();
SparseArray<ProcessRecord> procs = all.get(process);
if (procs != null && procs.size() > 0) {
proc = procs.valueAt(0);
@@ -19591,15 +18183,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
void onCoreSettingsChange(Bundle settings) {
- for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord processRecord = mLruProcesses.get(i);
- try {
- if (processRecord.thread != null) {
- processRecord.thread.setCoreSettings(settings);
- }
- } catch (RemoteException re) {
- /* ignore */
- }
+ synchronized (this) {
+ mProcessList.updateCoreSettingsLocked(settings);
}
}
@@ -19731,8 +18316,8 @@ public class ActivityManagerService extends IActivityManager.Stub
+ android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
- for (int i = 0; i < mLruProcesses.size(); i++) {
- ProcessRecord process = mLruProcesses.get(i);
+ for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
+ ProcessRecord process = mProcessList.mLruProcesses.get(i);
if (!processSanityChecksLocked(process)) {
continue;
}
@@ -19764,7 +18349,7 @@ public class ActivityManagerService extends IActivityManager.Stub
PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd.getFileDescriptor()));
pw.println("Binder transaction traces for all processes.\n");
- for (ProcessRecord process : mLruProcesses) {
+ for (ProcessRecord process : mProcessList.mLruProcesses) {
if (!processSanityChecksLocked(process)) {
continue;
}
@@ -19825,9 +18410,10 @@ public class ActivityManagerService extends IActivityManager.Stub
public void killForegroundAppsForUser(int userHandle) {
synchronized (ActivityManagerService.this) {
final ArrayList<ProcessRecord> procs = new ArrayList<>();
- final int NP = mProcessNames.getMap().size();
+ final int NP = mProcessList.mProcessNames.getMap().size();
for (int ip = 0; ip < NP; ip++) {
- final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final SparseArray<ProcessRecord> apps =
+ mProcessList.mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia = 0; ia < NA; ia++) {
final ProcessRecord app = apps.valueAt(ia);
@@ -19846,7 +18432,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final int N = procs.size();
for (int i = 0; i < N; i++) {
- removeProcessLocked(procs.get(i), false, true, "kill all fg");
+ mProcessList.removeProcessLocked(procs.get(i), false, true, "kill all fg");
}
}
}
@@ -20104,8 +18690,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (packageName == null) return false;
synchronized (ActivityManagerService.this) {
- for (int i = 0; i < mLruProcesses.size(); i++) {
- final ProcessRecord pr = mLruProcesses.get(i);
+ for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
+ final ProcessRecord pr = mProcessList.mLruProcesses.get(i);
if (pr.uid != uid) {
continue;
}
@@ -20338,6 +18924,110 @@ public class ActivityManagerService extends IActivityManager.Stub
(WindowProcessController) parentProc, aboveSystem, reason);
}
+
+ @Override
+ public void broadcastGlobalConfigurationChanged(int changes, boolean initLocale) {
+ synchronized (ActivityManagerService.this) {
+ Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
+ intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ if (initLocale || !mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ }
+
+ // Send a broadcast to PackageInstallers if the configuration change is interesting
+ // for the purposes of installing additional splits.
+ if (!initLocale && isSplitConfigurationChange(changes)) {
+ intent = new Intent(Intent.ACTION_SPLIT_CONFIGURATION_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+
+ // Typically only app stores will have this permission.
+ String[] permissions =
+ new String[] { android.Manifest.permission.INSTALL_PACKAGES };
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
+ permissions, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ }
+ }
+ }
+
+ /**
+ * Returns true if this configuration change is interesting enough to send an
+ * {@link Intent#ACTION_SPLIT_CONFIGURATION_CHANGED} broadcast.
+ */
+ private boolean isSplitConfigurationChange(int configDiff) {
+ return (configDiff & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_DENSITY)) != 0;
+ }
+
+ @Override
+ public void broadcastCloseSystemDialogs(String reason) {
+ synchronized (ActivityManagerService.this) {
+ final Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ if (reason != null) {
+ intent.putExtra("reason", reason);
+ }
+
+ broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ OP_NONE, null, false, false, -1, SYSTEM_UID, UserHandle.USER_ALL);
+ }
+ }
+
+ @Override
+ public void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) {
+ synchronized (ActivityManagerService.this) {
+ ActivityManagerService.this.killAllBackgroundProcessesExcept(
+ minTargetSdk, maxProcState);
+ }
+ }
+
+ @Override
+ public void startProcess(String processName, ApplicationInfo info,
+ boolean knownToBeDead, String hostingType, ComponentName hostingName) {
+ synchronized (ActivityManagerService.this) {
+ startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
+ hostingType, hostingName, false /* allowWhileBooting */,
+ false /* isolated */, true /* keepIfLarge */);
+ }
+ }
+
+ @Override
+ public void setDebugFlagsForStartingActivity(ActivityInfo aInfo, int startFlags,
+ ProfilerInfo profilerInfo) {
+ synchronized (ActivityManagerService.this) {
+ if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
+ setDebugApp(aInfo.processName, true, false);
+ }
+
+ if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
+ setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
+ }
+
+ if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
+ setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
+ }
+
+ if (profilerInfo != null) {
+ setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+ }
+ }
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
@@ -20519,8 +19209,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
try {
synchronized(this) {
- killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid), userId,
- ProcessList.FOREGROUND_APP_ADJ, false, true, true, false,
+ mProcessList.killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid),
+ userId, ProcessList.FOREGROUND_APP_ADJ, false, true, true, false,
"dep: " + packageName);
}
} finally {
@@ -20550,33 +19240,9 @@ public class ActivityManagerService extends IActivityManager.Stub
void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
- for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
- final ProcessRecord app = mLruProcesses.get(i);
- if (app.thread == null) {
- continue;
- }
- if (userId != UserHandle.USER_ALL && app.userId != userId) {
- continue;
- }
+ mProcessList.updateApplicationInfoLocked(packagesToUpdate, userId, updateFrameworkRes);
- final int packageCount = app.pkgList.size();
- for (int j = 0; j < packageCount; j++) {
- final String packageName = app.pkgList.keyAt(j);
- if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
- try {
- final ApplicationInfo ai = AppGlobals.getPackageManager()
- .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);
- if (ai != null) {
- app.thread.scheduleApplicationInfoChanged(ai);
- }
- } catch (RemoteException e) {
- Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",
- packageName, app));
- }
- }
- }
- }
if (updateFrameworkRes) {
// Update system server components that need to know about changed overlays. Because the
// overlay is applied in ActivityThread, we need to serialize through its thread too.
@@ -20598,7 +19264,8 @@ public class ActivityManagerService extends IActivityManager.Stub
public void attachAgent(String process, String path) {
try {
synchronized (this) {
- ProcessRecord proc = findProcessLocked(process, UserHandle.USER_SYSTEM, "attachAgent");
+ ProcessRecord proc = findProcessLocked(process, UserHandle.USER_SYSTEM,
+ "attachAgent");
if (proc == null || proc.thread == null) {
throw new IllegalArgumentException("Unknown process: " + process);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9f768a84d223..692b2d433dbc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -481,12 +481,12 @@ final class ActivityManagerShellCommand extends ShellCommand {
options.setLockTaskEnabled(true);
}
if (mWaitOption) {
- result = mTaskInterface.startActivityAndWait(null, null, intent, mimeType,
+ result = mInternal.startActivityAndWait(null, null, intent, mimeType,
null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
res = result.result;
} else {
- res = mTaskInterface.startActivityAsUser(null, null, intent, mimeType,
+ res = mInternal.startActivityAsUser(null, null, intent, mimeType,
null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 12ed726eca77..026c5cc3017d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3877,8 +3877,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// The activity that we are finishing may be over the lock screen. In this case, we do not
// want to consider activities that cannot be shown on the lock screen as running and should
// proceed with finishing the activity if there is no valid next top running activity.
- final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */);
+ final ActivityDisplay display = getDisplay();
+ final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */);
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible) {
@@ -3902,23 +3902,25 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
r.setState(FINISHING, "finishCurrentActivityLocked");
- final boolean finishingActivityInNonFocusedStack
- = r.getStack() != mStackSupervisor.getTopDisplayFocusedStack()
- && prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
+ final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE
+ && prevState == PAUSED && (r.getStack() != display.getFocusedStack()
+ || (next == null && display.topRunningActivity() == null));
if (mode == FINISH_IMMEDIATELY
|| (prevState == PAUSED
&& (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
- || finishingActivityInNonFocusedStack
+ || finishingInNonFocusedStackOrNoRunning
|| prevState == STOPPING
|| prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
- if (finishingActivityInNonFocusedStack) {
+ if (finishingInNonFocusedStackOrNoRunning) {
// Finishing activity that was in paused state and it was in not currently focused
- // stack, need to make something visible in its place.
+ // stack, need to make something visible in its place. Also if the display does not
+ // have running activity, the configuration may need to be updated for restoring
+ // original orientation of the display.
mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b7eba1100bcf..257a0042b510 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -21,6 +21,9 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
+import static android.app.ActivityManager.START_FLAG_DEBUG;
+import static android.app.ActivityManager.START_FLAG_NATIVE_DEBUGGING;
+import static android.app.ActivityManager.START_FLAG_TRACK_ALLOCATION;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
@@ -113,6 +116,7 @@ import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.AppOpsManager;
+import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.WaitResult;
@@ -1013,7 +1017,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
&& processName.equals(activity.processName)) {
try {
- if (realStartActivityLocked(activity, (ProcessRecord) app.mOwner,
+ if (realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
didSomething = true;
}
@@ -1210,75 +1214,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
ActivityRecord topRunningActivityLocked() {
- return topRunningActivityLocked(false /* considerKeyguardState */);
- }
-
- /**
- * Returns the top running activity in the focused stack. In the case the focused stack has no
- * such activity, the next focusable stack on top of a display is returned.
- * @param considerKeyguardState Indicates whether the locked state should be considered. if
- * {@code true} and the keyguard is locked, only activities that
- * can be shown on top of the keyguard will be considered.
- * @return The top running activity. {@code null} if none is available.
- */
- ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) {
- final ActivityStack focusedStack = getTopDisplayFocusedStack();
- ActivityRecord r = focusedStack.topRunningActivityLocked();
- if (r != null && isValidTopRunningActivity(r, considerKeyguardState)) {
- return r;
- }
-
- // Look in other non-focused and non-home stacks.
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
-
- // TODO: We probably want to consider the top fullscreen stack as we could have a pinned
- // stack on top.
- final ActivityStack topStack = display.getTopStack();
-
- // Only consider focusable top stacks other than the current focused one.
- if (topStack == null || !topStack.isFocusable() || topStack == focusedStack) {
- continue;
- }
-
- final ActivityRecord topActivity = topStack.topRunningActivityLocked();
-
- // Skip if no top activity.
- if (topActivity == null) {
- continue;
- }
-
-
- // This activity can be considered the top running activity if we are not
- // considering the locked state, the keyguard isn't locked, or we can show when
- // locked.
- if (isValidTopRunningActivity(topActivity, considerKeyguardState)) {
+ final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity();
+ if (topActivity != null) {
return topActivity;
}
}
-
return null;
}
- /**
- * Verifies an {@link ActivityRecord} can be the top activity based on keyguard state and
- * whether we are considering it.
- */
- private boolean isValidTopRunningActivity(ActivityRecord record,
- boolean considerKeyguardState) {
- if (!considerKeyguardState) {
- return true;
- }
-
- final boolean keyguardLocked = getKeyguardController().isKeyguardLocked();
-
- if (!keyguardLocked) {
- return true;
- }
-
- return record.canShowWhenLocked();
- }
-
@VisibleForTesting
void getRunningTasks(int maxNum, List<RunningTaskInfo> list,
@ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode,
@@ -1300,20 +1244,17 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Don't debug things in the system process
if (!aInfo.processName.equals("system")) {
- if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
- mService.mAm.setDebugApp(aInfo.processName, true, false);
- }
-
- if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
- mService.mAm.setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
- }
-
- if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
- mService.mAm.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
- }
-
- if (profilerInfo != null) {
- mService.mAm.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+ if ((startFlags & (START_FLAG_DEBUG | START_FLAG_NATIVE_DEBUGGING
+ | START_FLAG_TRACK_ALLOCATION)) != 0 || profilerInfo != null) {
+ /**
+ * Assume safe to call into AMS synchronously because the call that set these
+ * flags should have originated from AMS which will already have its lock held.
+ * @see ActivityManagerService#startActivityAndWait(IApplicationThread, String,
+ * Intent, String, IBinder, String, int, int, ProfilerInfo, Bundle, int)
+ * TODO(b/80414790): Investigate a better way of untangling this.
+ */
+ mService.mAmInternal.setDebugFlagsForStartingActivity(
+ aInfo, startFlags, profilerInfo);
}
}
final String intentLaunchToken = intent.getLaunchToken();
@@ -1360,7 +1301,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return resolveActivity(intent, rInfo, startFlags, profilerInfo);
}
- final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
+ private boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
if (!allPausedActivitiesComplete()) {
@@ -1379,7 +1320,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
beginDeferResume();
try {
- final WindowProcessController proc = app.getWindowProcessController();
r.startFreezingScreenLocked(proc, 0);
// schedule launch ticks to collect information about slow apps.
@@ -1415,15 +1355,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
- if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
+ if ((r.userId != proc.mUserId) || (r.appInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.appInfo.uid
+ " info.ai.uid=" + applicationInfoUid
- + " old=" + r.app + " new=" + app);
+ + " old=" + r.app + " new=" + proc);
}
- app.waitingToKill = null;
+ proc.clearWaitingToKill();
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
@@ -1442,7 +1382,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
try {
- if (app.thread == null) {
+ if (!proc.hasThread()) {
throw new RemoteException();
}
List<ResultInfo> results = null;
@@ -1468,50 +1408,29 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
r.forceNewConfig = false;
mService.getAppWarningsLocked().onStartActivity(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
- ProfilerInfo profilerInfo = null;
- if (mService.mAm.mProfileApp != null && mService.mAm.mProfileApp.equals(app.processName)) {
- if (mService.mAm.mProfileProc == null || mService.mAm.mProfileProc == app) {
- mService.mAm.mProfileProc = app;
- ProfilerInfo profilerInfoSvc = mService.mAm.mProfilerInfo;
- if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
- if (profilerInfoSvc.profileFd != null) {
- try {
- profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
- } catch (IOException e) {
- profilerInfoSvc.closeFd();
- }
- }
+ ProfilerInfo profilerInfo = proc.onStartActivity(mService.mTopProcessState);
- profilerInfo = new ProfilerInfo(profilerInfoSvc);
- }
- }
- }
-
- app.hasShownUi = true;
- app.setPendingUiClean(true);
- app.forceProcessStateUpTo(mService.mTopProcessState);
// Because we could be starting an Activity in the system process this may not go
// across a Binder interface which would create a new Configuration. Consequently
// we have to always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
- app.getWindowProcessController().getConfiguration(),
- r.getMergedOverrideConfiguration());
+ proc.getConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.icicle);
// Create activity launch transaction.
- final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
- r.appToken);
+ final ClientTransaction clientTransaction = ClientTransaction.obtain(
+ proc.getThread(), r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
- r.launchedFromPackage, task.voiceInteractor, app.getReportedProcState(),
+ r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
mService.isNextTransitionForward(), profilerInfo));
@@ -1527,12 +1446,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
- if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
+ if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
&& mService.mHasHeavyWeightFeature) {
// This may be a heavy-weight process! Note that the package manager will ensure
// that only activity can run in the main process of the .apk, which is the only
// thing that will be considered heavy-weight.
- if (app.processName.equals(app.info.packageName)) {
+ if (proc.mName.equals(proc.mInfo.packageName)) {
if (mService.mHeavyWeightProcess != null
&& mService.mHeavyWeightProcess != proc) {
Slog.w(TAG, "Starting new heavy weight process " + proc
@@ -1545,12 +1464,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
} catch (RemoteException e) {
if (r.launchFailed) {
- // This is the second time we failed -- finish activity
- // and give up.
+ // This is the second time we failed -- finish activity and give up.
Slog.e(TAG, "Second failure launching "
- + r.intent.getComponent().flattenToShortString()
- + ", giving up", e);
- mService.mAm.appDiedLocked(app);
+ + r.intent.getComponent().flattenToShortString() + ", giving up", e);
+ proc.appDied();
stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"2nd-crash", false);
return false;
@@ -1659,24 +1576,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- void startSpecificActivityLocked(ActivityRecord r,
- boolean andResume, boolean checkConfig) {
+ void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
- ProcessRecord app = mService.mAm.getProcessRecordLocked(r.processName,
- r.info.applicationInfo.uid, true);
+ final WindowProcessController wpc =
+ mService.getProcessController(r.processName, r.info.applicationInfo.uid);
- if (app != null && app.thread != null) {
+ if (wpc != null && wpc.hasThread()) {
try {
- if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
+ if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
- // Don't add this if it is a platform component that is marked
- // to run in multiple processes, because this is actually
- // part of the framework so doesn't make sense to track as a
- // separate apk in the process.
- app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
- mService.mAm.mProcessStats);
+ // Don't add this if it is a platform component that is marked to run in
+ // multiple processes, because this is actually part of the framework so doesn't
+ // make sense to track as a separate apk in the process.
+ wpc.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode);
}
- realStartActivityLocked(r, app, andResume, checkConfig);
+ realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
@@ -1687,8 +1601,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// restart the application.
}
- mService.mAm.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
- "activity", r.intent.getComponent(), false, false, true);
+ // Post message to start process to avoid possible deadlock of calling into AMS with the
+ // ATMS lock held.
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
+ r.info.applicationInfo, true, "activity", r.intent.getComponent());
+ mService.mH.sendMessage(msg);
}
void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 2d2701785d03..f79d9aa9ba67 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -4670,14 +4670,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return kept;
}
- /**
- * Returns true if this configuration change is interesting enough to send an
- * {@link Intent#ACTION_SPLIT_CONFIGURATION_CHANGED} broadcast.
- */
- private static boolean isSplitConfigurationChange(int configDiff) {
- return (configDiff & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_DENSITY)) != 0;
- }
-
/** Update default (global) configuration and notify listeners about changes. */
private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
boolean persistent, int userId, boolean deferResume) {
@@ -4777,38 +4769,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
app.onConfigurationChanged(configCopy);
}
- Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_FOREGROUND
- | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
- mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
- if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
- intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
- | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
- | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
- if (initLocale || !mAm.mProcessesReady) {
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- }
- mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
- }
-
- // Send a broadcast to PackageInstallers if the configuration change is interesting
- // for the purposes of installing additional splits.
- if (!initLocale && isSplitConfigurationChange(changes)) {
- intent = new Intent(Intent.ACTION_SPLIT_CONFIGURATION_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-
- // Typically only app stores will have this permission.
- String[] permissions = new String[] { android.Manifest.permission.INSTALL_PACKAGES };
- mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, permissions,
- OP_NONE, null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
- }
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::broadcastGlobalConfigurationChanged,
+ mAmInternal, changes, initLocale);
+ mH.sendMessage(msg);
// Override configuration of the default display duplicates global config, so we need to
// update it also. This will also notify WindowManager about changes.
@@ -4877,8 +4841,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (isDensityChange && displayId == DEFAULT_DISPLAY) {
mAppWarnings.onDensityChanged();
- mAm.killAllBackgroundProcessesExcept(N,
- ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ // Post message to start process to avoid possible deadlock of calling into AMS with
+ // the ATMS lock held.
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::killAllBackgroundProcessesExcept, mAmInternal,
+ N, ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ mH.sendMessage(msg);
}
}
@@ -5446,7 +5414,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return newInfo;
}
- private WindowProcessController getProcessController(String processName, int uid) {
+ WindowProcessController getProcessController(String processName, int uid) {
if (uid == SYSTEM_UID) {
// The system gets to run in any process. If there are multiple processes with the same
// uid, just pick the first (this should never happen).
@@ -5896,6 +5864,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void finishHeavyWeightApp() {
synchronized (mGlobalLock) {
+ if (mHeavyWeightProcess != null) {
+ mHeavyWeightProcess.finishActivities();
+ }
ActivityTaskManagerService.this.clearHeavyWeightProcessIfEquals(
mHeavyWeightProcess);
}
@@ -6247,20 +6218,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
}
- Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- if (reason != null) {
- intent.putExtra("reason", reason);
- }
mWindowManager.closeSystemDialogs(reason);
mStackSupervisor.closeSystemDialogsLocked();
-
- mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false,
- -1, SYSTEM_UID, UserHandle.USER_ALL);
}
+ // Call into AM outside the synchronized block.
+ mAmInternal.broadcastCloseSystemDialogs(reason);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 83c4ab50db3a..e8ec0574610c 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -121,7 +121,7 @@ class AppErrors {
proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+ final ProcessRecord r = mService.getProcessNames().get(pname, puid);
if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) {
continue;
}
@@ -148,7 +148,7 @@ class AppErrors {
proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+ final ProcessRecord r = mService.getProcessNames().get(pname, puid);
if (dumpPackage != null && (r == null
|| !r.pkgList.containsKey(dumpPackage))) {
continue;
@@ -181,7 +181,7 @@ class AppErrors {
final int uidCount = uids.size();
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+ final ProcessRecord r = mService.getProcessNames().get(pname, puid);
if (dumpPackage != null && (r == null
|| !r.pkgList.containsKey(dumpPackage))) {
continue;
@@ -211,7 +211,7 @@ class AppErrors {
final int uidCount = uids.size();
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.mProcessNames.get(pname, puid);
+ final ProcessRecord r = mService.getProcessNames().get(pname, puid);
if (dumpPackage != null && (r == null
|| !r.pkgList.containsKey(dumpPackage))) {
continue;
@@ -471,7 +471,7 @@ class AppErrors {
stopReportingCrashesLocked(r);
}
if (res == AppErrorDialog.RESTART) {
- mService.removeProcessLocked(r, false, true, "crash");
+ mService.mProcessList.removeProcessLocked(r, false, true, "crash");
if (taskId != INVALID_TASK_ID) {
try {
mService.mActivityTaskManager.startActivityFromRecents(taskId,
@@ -489,7 +489,7 @@ class AppErrors {
// Kill it with fire!
mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
if (!r.isPersistent()) {
- mService.removeProcessLocked(r, false, false, "crash");
+ mService.mProcessList.removeProcessLocked(r, false, false, "crash");
mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
}
} finally {
@@ -551,7 +551,7 @@ class AppErrors {
} else {
// Huh.
Process.killProcess(pid);
- ActivityManagerService.killProcessGroup(uid, pid);
+ ProcessList.killProcessGroup(uid, pid);
}
}
return true;
@@ -714,7 +714,7 @@ class AppErrors {
// Don't let services in this process be restarted and potentially
// annoy the user repeatedly. Unless it is persistent, since those
// processes run critical code.
- mService.removeProcessLocked(app, false, tryAgain, "crash");
+ mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash");
mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
if (!showBackground) {
return false;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a13cf4d3d2d1..a0977be0e25d 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -286,7 +286,7 @@ public final class BroadcastQueue {
r.curApp = app;
app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
- mService.updateLruProcessLocked(app, false, null);
+ mService.mProcessList.updateLruProcessLocked(app, false, null);
if (!skipOomAdj) {
mService.updateOomAdjLocked();
}
@@ -892,7 +892,7 @@ public final class BroadcastQueue {
isDead = proc == null || proc.isCrashing();
}
} else {
- final ProcessRecord proc = mService.mProcessNames.get(
+ final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
isDead = proc == null || !proc.pendingStart;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9e7ce3204444..3f172cc11468 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -16,19 +16,79 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
+import static android.os.Process.FIRST_ISOLATED_UID;
+import static android.os.Process.LAST_ISOLATED_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.getFreeMemory;
+import static android.os.Process.getTotalMemory;
+import static android.os.Process.killProcessQuiet;
+import static android.os.Process.startWebView;
+
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-
+import static com.android.server.am.ActivityManagerService.PERSISTENT_MASK;
+import static com.android.server.am.ActivityManagerService.PROC_START_TIMEOUT;
+import static com.android.server.am.ActivityManagerService.PROC_START_TIMEOUT_MSG;
+import static com.android.server.am.ActivityManagerService.PROC_START_TIMEOUT_WITH_WRAPPER;
+import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
+import static com.android.server.am.ActivityManagerService.TAG_LRU;
+import static com.android.server.am.ActivityManagerService.TAG_PROCESSES;
+import static com.android.server.am.ActivityManagerService.TAG_PSS;
+import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
+
+import dalvik.system.VMRuntime;
+
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import android.app.ActivityManager;
+import android.app.AppGlobals;
import android.app.AppProtoEnums;
+import android.app.IApplicationThread;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
+import android.os.FactoryTest;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.StrictMode;
import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ProcessMap;
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.os.Zygote;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.MemInfoReader;
+import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
+import com.android.server.Watchdog;
+import com.android.server.pm.dex.DexManager;
import com.android.server.wm.WindowManagerService;
import android.content.res.Resources;
@@ -36,7 +96,15 @@ import android.graphics.Point;
import android.os.SystemProperties;
import android.net.LocalSocketAddress;
import android.net.LocalSocket;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.os.storage.StorageManagerInternal;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.LongSparseArray;
import android.util.Slog;
+import android.util.SparseArray;
+import android.util.StatsLog;
import android.view.Display;
/**
@@ -47,7 +115,7 @@ public final class ProcessList {
// The minimum time we allow between crashes, for us to consider this
// application to be bad and stop and its services and reject broadcasts.
- static final int MIN_CRASH_INTERVAL = 60*1000;
+ static final int MIN_CRASH_INTERVAL = 60 * 1000;
// OOM adjustments for processes in various states:
@@ -129,7 +197,7 @@ public final class ProcessList {
static final int NATIVE_ADJ = -1000;
// Memory pages are 4K.
- static final int PAGE_SIZE = 4*1024;
+ static final int PAGE_SIZE = 4 * 1024;
// Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
static final int SCHED_GROUP_BACKGROUND = 0;
@@ -148,7 +216,7 @@ public final class ProcessList {
static final int MIN_CACHED_APPS = 2;
// We allow empty processes to stick around for at most 30 minutes.
- static final long MAX_EMPTY_TIME = 30*60*1000;
+ static final long MAX_EMPTY_TIME = 30 * 60 * 1000;
// Threshold of number of cached+empty where we consider memory critical.
static final int TRIM_CRITICAL_THRESHOLD = 3;
@@ -168,6 +236,12 @@ public final class ProcessList {
static final byte LMK_PROCREMOVE = 2;
static final byte LMK_PROCPURGE = 3;
+ ActivityManagerService mService = null;
+
+ // To kill process groups asynchronously
+ static KillHandler sKillHandler = null;
+ static ServiceThread sKillThread = null;
+
// These are the various interesting memory levels that we will give to
// the OOM killer. Note that the OOM killer only supports 6 slots, so we
// can't give it a different value for every possible kind of process.
@@ -199,6 +273,123 @@ public final class ProcessList {
private static LocalSocket sLmkdSocket;
private static OutputStream sLmkdOutputStream;
+ /**
+ * Temporary to avoid allocations. Protected by main lock.
+ */
+ @GuardedBy("mService")
+ final StringBuilder mStringBuilder = new StringBuilder(256);
+
+ /**
+ * A global counter for generating sequence numbers.
+ * This value will be used when incrementing sequence numbers in individual uidRecords.
+ *
+ * Having a global counter ensures that seq numbers are monotonically increasing for a
+ * particular uid even when the uidRecord is re-created.
+ */
+ @GuardedBy("mService")
+ @VisibleForTesting
+ long mProcStateSeqCounter = 0;
+
+ /**
+ * A global counter for generating sequence numbers to uniquely identify pending process starts.
+ */
+ @GuardedBy("mService")
+ private long mProcStartSeqCounter = 0;
+
+ /**
+ * Contains {@link ProcessRecord} objects for pending process starts.
+ *
+ * Mapping: {@link #mProcStartSeqCounter} -> {@link ProcessRecord}
+ */
+ @GuardedBy("mService")
+ final LongSparseArray<ProcessRecord> mPendingStarts = new LongSparseArray<>();
+
+ /**
+ * List of running applications, sorted by recent usage.
+ * The first entry in the list is the least recently used.
+ */
+ final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
+
+ /**
+ * Where in mLruProcesses that the processes hosting activities start.
+ */
+ int mLruProcessActivityStart = 0;
+
+ /**
+ * Where in mLruProcesses that the processes hosting services start.
+ * This is after (lower index) than mLruProcessesActivityStart.
+ */
+ int mLruProcessServiceStart = 0;
+
+ /**
+ * Current sequence id for process LRU updating.
+ */
+ int mLruSeq = 0;
+
+ /**
+ * The currently running isolated processes.
+ */
+ final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
+
+ /**
+ * Counter for assigning isolated process uids, to avoid frequently reusing the
+ * same ones.
+ */
+ int mNextIsolatedProcessUid = 0;
+
+ /**
+ * Processes that are being forcibly torn down.
+ */
+ final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();
+
+ /**
+ * All of the applications we currently have running organized by name.
+ * The keys are strings of the application package name (as
+ * returned by the package manager), and the keys are ApplicationRecord
+ * objects.
+ */
+ final MyProcessMap mProcessNames = new MyProcessMap();
+
+ final class MyProcessMap extends ProcessMap<ProcessRecord> {
+ @Override
+ public ProcessRecord put(String name, int uid, ProcessRecord value) {
+ final ProcessRecord r = super.put(name, uid, value);
+ mService.mAtmInternal.onProcessAdded(r.getWindowProcessController());
+ return r;
+ }
+
+ @Override
+ public ProcessRecord remove(String name, int uid) {
+ final ProcessRecord r = super.remove(name, uid);
+ mService.mAtmInternal.onProcessRemoved(name, uid);
+ return r;
+ }
+ }
+
+ final class KillHandler extends Handler {
+ static final int KILL_PROCESS_GROUP_MSG = 4000;
+
+ public KillHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case KILL_PROCESS_GROUP_MSG:
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup");
+ Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ break;
+
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
+ //////////////////// END FIELDS ////////////////////
+
ProcessList() {
MemInfoReader minfo = new MemInfoReader();
minfo.readMemInfo();
@@ -206,6 +397,16 @@ public final class ProcessList {
updateOomLevels(0, 0, false);
}
+ void init(ActivityManagerService service) {
+ mService = service;
+ if (sKillHandler == null) {
+ sKillThread = new ServiceThread(TAG + ":kill",
+ THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
+ sKillThread.start();
+ sKillHandler = new KillHandler(sKillThread.getLooper());
+ }
+ }
+
void applyDisplaySize(WindowManagerService wm) {
if (!mHaveDisplaySize) {
Point p = new Point();
@@ -221,12 +422,12 @@ public final class ProcessList {
private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
// Scale buckets from avail memory: at 300MB we use the lowest values to
// 700MB or more for the top values.
- float scaleMem = ((float)(mTotalMemMb-350))/(700-350);
+ float scaleMem = ((float) (mTotalMemMb - 350)) / (700 - 350);
// Scale buckets from screen size.
- int minSize = 480*800; // 384000
- int maxSize = 1280*800; // 1024000 230400 870400 .264
- float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
+ int minSize = 480 * 800; // 384000
+ int maxSize = 1280 * 800; // 1024000 230400 870400 .264
+ float scaleDisp = ((float)(displayWidth * displayHeight) - minSize) / (maxSize - minSize);
if (false) {
Slog.i("XXXXXX", "scaleMem=" + scaleMem);
Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth
@@ -246,27 +447,27 @@ public final class ProcessList {
final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
- for (int i=0; i<mOomAdj.length; i++) {
+ for (int i = 0; i < mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
if (is64bit) {
// Increase the high min-free levels for cached processes for 64-bit
- if (i == 4) high = (high*3)/2;
- else if (i == 5) high = (high*7)/4;
+ if (i == 4) high = (high * 3) / 2;
+ else if (i == 5) high = (high * 7) / 4;
}
- mOomMinFree[i] = (int)(low + ((high-low)*scale));
+ mOomMinFree[i] = (int)(low + ((high - low) * scale));
}
if (minfree_abs >= 0) {
- for (int i=0; i<mOomAdj.length; i++) {
+ for (int i = 0; i < mOomAdj.length; i++) {
mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i]
/ mOomMinFree[mOomAdj.length - 1]);
}
}
if (minfree_adj != 0) {
- for (int i=0; i<mOomAdj.length; i++) {
- mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i]
+ for (int i = 0; i < mOomAdj.length; i++) {
+ mOomMinFree[i] += (int)((float) minfree_adj * mOomMinFree[i]
/ mOomMinFree[mOomAdj.length - 1]);
if (mOomMinFree[i] < 0) {
mOomMinFree[i] = 0;
@@ -277,13 +478,15 @@ public final class ProcessList {
// The maximum size we will restore a process from cached to background, when under
// memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
// before killing background processes.
- mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3;
+ mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024) / 3;
// Ask the kernel to try to keep enough memory free to allocate 3 full
// screen 32bpp buffers without entering direct reclaim.
int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
- int reserve_adj = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAdjust);
- int reserve_abs = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAbsolute);
+ int reserve_adj = Resources.getSystem().getInteger(
+ com.android.internal.R.integer.config_extraFreeKbytesAdjust);
+ int reserve_abs = Resources.getSystem().getInteger(
+ com.android.internal.R.integer.config_extraFreeKbytesAbsolute);
if (reserve_abs >= 0) {
reserve = reserve_abs;
@@ -297,10 +500,10 @@ public final class ProcessList {
}
if (write) {
- ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1));
+ ByteBuffer buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
buf.putInt(LMK_TARGET);
- for (int i=0; i<mOomAdj.length; i++) {
- buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE);
+ for (int i = 0; i < mOomAdj.length; i++) {
+ buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
buf.putInt(mOomAdj[i]);
}
@@ -320,7 +523,7 @@ public final class ProcessList {
if (space == null) return prefix;
return prefix + " ";
}
- return prefix + "+" + Integer.toString(val-base);
+ return prefix + "+" + Integer.toString(val - base);
}
public static String makeOomAdjString(int setAdj) {
@@ -477,7 +680,7 @@ public final class ProcessList {
}
public static void appendRamKb(StringBuilder sb, long ramKb) {
- for (int j=0, fact=10; j<6; j++, fact*=10) {
+ for (int j = 0, fact = 10; j < 6; j++, fact *= 10) {
if (ramKb < fact) {
sb.append(' ');
}
@@ -737,12 +940,12 @@ public final class ProcessList {
}
long getMemLevel(int adjustment) {
- for (int i=0; i<mOomAdj.length; i++) {
+ for (int i = 0; i < mOomAdj.length; i++) {
if (adjustment <= mOomAdj[i]) {
return mOomMinFree[i] * 1024;
}
}
- return mOomMinFree[mOomAdj.length-1] * 1024;
+ return mOomMinFree[mOomAdj.length - 1] * 1024;
}
/**
@@ -858,4 +1061,1515 @@ public final class ProcessList {
}
}
}
+
+ static void killProcessGroup(int uid, int pid) {
+ /* static; one-time init here */
+ if (sKillHandler != null) {
+ sKillHandler.sendMessage(
+ sKillHandler.obtainMessage(KillHandler.KILL_PROCESS_GROUP_MSG, uid, pid));
+ } else {
+ Slog.w(TAG, "Asked to kill process group before system bringup!");
+ Process.killProcessGroup(uid, pid);
+ }
+ }
+
+ final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean
+ keepIfLarge) {
+ if (uid == SYSTEM_UID) {
+ // The system gets to run in any process. If there are multiple
+ // processes with the same uid, just pick the first (this
+ // should never happen).
+ SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
+ if (procs == null) return null;
+ final int procCount = procs.size();
+ for (int i = 0; i < procCount; i++) {
+ final int procUid = procs.keyAt(i);
+ if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ // Don't use an app process or different user process for system component.
+ continue;
+ }
+ return procs.valueAt(i);
+ }
+ }
+ ProcessRecord proc = mProcessNames.get(processName, uid);
+ if (false && proc != null && !keepIfLarge
+ && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ && proc.lastCachedPss >= 4000) {
+ // Turn this condition on to cause killing to happen regularly, for testing.
+ if (proc.baseProcessTracker != null) {
+ proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
+ for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+ ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+ StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
+ proc.info.uid,
+ holder.state.getName(),
+ holder.state.getPackage(),
+ proc.lastCachedPss, holder.appVersion);
+ }
+ }
+ proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
+ } else if (proc != null && !keepIfLarge
+ && mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
+ && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc
+ .lastCachedPss);
+ if (proc.lastCachedPss >= getCachedRestoreThresholdKb()) {
+ if (proc.baseProcessTracker != null) {
+ proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList,
+ proc.lastCachedPss);
+ for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+ ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+ StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
+ proc.info.uid,
+ holder.state.getName(),
+ holder.state.getPackage(),
+ proc.lastCachedPss, holder.appVersion);
+ }
+ }
+ proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
+ }
+ }
+ return proc;
+ }
+
+ void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
+ final long homeAppMem = getMemLevel(HOME_APP_ADJ);
+ final long cachedAppMem = getMemLevel(CACHED_APP_MIN_ADJ);
+ outInfo.availMem = getFreeMemory();
+ outInfo.totalMem = getTotalMemory();
+ outInfo.threshold = homeAppMem;
+ outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
+ outInfo.hiddenAppThreshold = cachedAppMem;
+ outInfo.secondaryServerThreshold = getMemLevel(SERVICE_ADJ);
+ outInfo.visibleAppThreshold = getMemLevel(VISIBLE_APP_ADJ);
+ outInfo.foregroundAppThreshold = getMemLevel(FOREGROUND_APP_ADJ);
+ }
+
+ ProcessRecord findAppProcessLocked(IBinder app, String reason) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ ProcessRecord p = apps.valueAt(ia);
+ if (p.thread != null && p.thread.asBinder() == app) {
+ return p;
+ }
+ }
+ }
+
+ Slog.w(TAG, "Can't find mystery application for " + reason
+ + " from pid=" + Binder.getCallingPid()
+ + " uid=" + Binder.getCallingUid() + ": " + app);
+ return null;
+ }
+
+ private void checkSlow(long startTime, String where) {
+ long now = SystemClock.uptimeMillis();
+ if ((now - startTime) > 50) {
+ // If we are taking more than 50ms, log about it.
+ Slog.w(TAG, "Slow operation: " + (now - startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
+ * @return {@code true} if process start is successful, false otherwise.
+ * @param app
+ * @param hostingType
+ * @param hostingNameStr
+ * @param disableHiddenApiChecks
+ * @param abiOverride
+ */
+ @GuardedBy("mService")
+ boolean startProcessLocked(ProcessRecord app, String hostingType,
+ String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
+ if (app.pendingStart) {
+ return true;
+ }
+ long startTime = SystemClock.elapsedRealtime();
+ if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
+ checkSlow(startTime, "startProcess: removing from pids map");
+ synchronized (mService.mPidsSelfLocked) {
+ mService.mPidsSelfLocked.remove(app.pid);
+ mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+ }
+ checkSlow(startTime, "startProcess: done removing from pids map");
+ app.setPid(0);
+ }
+
+ if (DEBUG_PROCESSES && mService.mProcessesOnHold.contains(app)) Slog.v(
+ TAG_PROCESSES,
+ "startProcessLocked removing on hold: " + app);
+ mService.mProcessesOnHold.remove(app);
+
+ checkSlow(startTime, "startProcess: starting to update cpu stats");
+ mService.updateCpuStats();
+ checkSlow(startTime, "startProcess: done updating cpu stats");
+
+ try {
+ try {
+ final int userId = UserHandle.getUserId(app.uid);
+ AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+
+ int uid = app.uid;
+ int[] gids = null;
+ int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
+ if (!app.isolated) {
+ int[] permGids = null;
+ try {
+ checkSlow(startTime, "startProcess: getting gids from package manager");
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ permGids = pm.getPackageGids(app.info.packageName,
+ MATCH_DIRECT_BOOT_AUTO, app.userId);
+ StorageManagerInternal storageManagerInternal = LocalServices.getService(
+ StorageManagerInternal.class);
+ mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
+ app.info.packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+
+ /*
+ * Add shared application and profile GIDs so applications can share some
+ * resources like shared libraries and access user-wide resources
+ */
+ if (ArrayUtils.isEmpty(permGids)) {
+ gids = new int[3];
+ } else {
+ gids = new int[permGids.length + 3];
+ System.arraycopy(permGids, 0, gids, 3, permGids.length);
+ }
+ gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
+ gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
+ gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+
+ // Replace any invalid GIDs
+ if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
+ if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
+ }
+ checkSlow(startTime, "startProcess: building args");
+ if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
+ uid = 0;
+ }
+ int runtimeFlags = 0;
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
+ runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
+ // Also turn on CheckJNI for debuggable apps. It's quite
+ // awkward to turn on otherwise.
+ runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
+ }
+ // Run the app in safe mode if its manifest requests so or the
+ // system is booted in safe mode.
+ if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
+ mService.mSafeMode == true) {
+ runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
+ }
+ if ("1".equals(SystemProperties.get("debug.checkjni"))) {
+ runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
+ }
+ String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
+ if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
+ runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
+ }
+ String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
+ if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
+ runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
+ }
+ if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
+ runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
+ }
+ if ("1".equals(SystemProperties.get("debug.assert"))) {
+ runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;
+ }
+ if (mService.mNativeDebuggingApp != null
+ && mService.mNativeDebuggingApp.equals(app.processName)) {
+ // Enable all debug flags required by the native debugger.
+ runtimeFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything
+ runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info
+ runtimeFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations
+ mService.mNativeDebuggingApp = null;
+ }
+
+ if (app.info.isPrivilegedApp() &&
+ DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet())) {
+ runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
+ }
+
+ if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
+ app.info.maybeUpdateHiddenApiEnforcementPolicy(
+ mService.mHiddenApiBlacklist.getPolicyForPrePApps(),
+ mService.mHiddenApiBlacklist.getPolicyForPApps());
+ @ApplicationInfo.HiddenApiEnforcementPolicy int policy =
+ app.info.getHiddenApiEnforcementPolicy();
+ int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
+ if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
+ throw new IllegalStateException("Invalid API policy: " + policy);
+ }
+ runtimeFlags |= policyBits;
+ }
+
+ String invokeWith = null;
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ // Debuggable apps may include a wrapper script with their library directory.
+ String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ try {
+ if (new File(wrapperFileName).exists()) {
+ invokeWith = "/system/bin/logwrapper " + wrapperFileName;
+ }
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+
+ String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
+ if (requiredAbi == null) {
+ requiredAbi = Build.SUPPORTED_ABIS[0];
+ }
+
+ String instructionSet = null;
+ if (app.info.primaryCpuAbi != null) {
+ instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
+ }
+
+ app.gids = gids;
+ app.setRequiredAbi(requiredAbi);
+ app.instructionSet = instructionSet;
+
+ // the per-user SELinux context must be set
+ if (TextUtils.isEmpty(app.info.seInfoUser)) {
+ Slog.wtf(ActivityManagerService.TAG, "SELinux tag not defined",
+ new IllegalStateException("SELinux tag not defined for "
+ + app.info.packageName + " (uid " + app.uid + ")"));
+ }
+ final String seInfo = app.info.seInfo
+ + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
+ // Start the process. It will either succeed and return a result containing
+ // the PID of the new process, or else throw a RuntimeException.
+ final String entryPoint = "android.app.ActivityThread";
+
+ return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
+ runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
+ startTime);
+ } catch (RuntimeException e) {
+ Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);
+
+ // Something went very wrong while trying to start this process; one
+ // common case is when the package is frozen due to an active
+ // upgrade. To recover, clean up any active bookkeeping related to
+ // starting this process. (We already invoked this method once when
+ // the package was initially frozen through KILL_APPLICATION_MSG, so
+ // it doesn't hurt to use it again.)
+ mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
+ false, false, true, false, false, app.userId, "start failure");
+ return false;
+ }
+ }
+
+ @GuardedBy("mService")
+ boolean startProcessLocked(String hostingType, String hostingNameStr,
+ String entryPoint,
+ ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
+ String seInfo, String requiredAbi, String instructionSet, String invokeWith,
+ long startTime) {
+ app.pendingStart = true;
+ app.killedByAm = false;
+ app.removed = false;
+ app.killed = false;
+ final long startSeq = app.startSeq = ++mProcStartSeqCounter;
+ app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
+ if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
+ if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
+ "Posting procStart msg for " + app.toShortString());
+ mService.mProcStartHandler.post(() -> {
+ try {
+ synchronized (mService) {
+ final String reason = isProcStartValidLocked(app, startSeq);
+ if (reason != null) {
+ Slog.w(TAG_PROCESSES, app + " not valid anymore,"
+ + " don't start process, " + reason);
+ app.pendingStart = false;
+ return;
+ }
+ app.setUsingWrapper(invokeWith != null
+ || SystemProperties.get("wrap." + app.processName) != null);
+ mPendingStarts.put(startSeq, app);
+ }
+ final Process.ProcessStartResult startResult = startProcess(app.hostingType,
+ entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
+ app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
+ synchronized (mService) {
+ handleProcessStartedLocked(app, startResult, startSeq);
+ }
+ } catch (RuntimeException e) {
+ synchronized (mService) {
+ Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ + app.processName, e);
+ mPendingStarts.remove(startSeq);
+ app.pendingStart = false;
+ mService.forceStopPackageLocked(app.info.packageName,
+ UserHandle.getAppId(app.uid),
+ false, false, true, false, false, app.userId, "start failure");
+ }
+ }
+ });
+ return true;
+ } else {
+ try {
+ final Process.ProcessStartResult startResult = startProcess(hostingType,
+ entryPoint, app,
+ uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
+ invokeWith, startTime);
+ handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
+ startSeq, false);
+ } catch (RuntimeException e) {
+ Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ + app.processName, e);
+ app.pendingStart = false;
+ mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
+ false, false, true, false, false, app.userId, "start failure");
+ }
+ return app.pid > 0;
+ }
+ }
+
+ private Process.ProcessStartResult startProcess(String hostingType, String entryPoint,
+ ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
+ String seInfo, String requiredAbi, String instructionSet, String invokeWith,
+ long startTime) {
+ try {
+ final String[] packageNames = mService.mContext.getPackageManager()
+ .getPackagesForUid(uid);
+ final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class)
+ .getVisibleVolumesForUser(UserHandle.getUserId(uid));
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
+ app.processName);
+ checkSlow(startTime, "startProcess: asking zygote to start proc");
+ final Process.ProcessStartResult startResult;
+ if (hostingType.equals("webview_service")) {
+ startResult = startWebView(entryPoint,
+ app.processName, uid, uid, gids, runtimeFlags, mountExternal,
+ app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
+ app.info.dataDir, null, app.info.packageName,
+ packageNames, visibleVolIds,
+ new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+ } else {
+ startResult = Process.start(entryPoint,
+ app.processName, uid, uid, gids, runtimeFlags, mountExternal,
+ app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
+ app.info.dataDir, invokeWith, app.info.packageName,
+ packageNames, visibleVolIds,
+ new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+ }
+ checkSlow(startTime, "startProcess: returned from zygote!");
+ return startResult;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+
+ @GuardedBy("mService")
+ final void startProcessLocked(ProcessRecord app,
+ String hostingType, String hostingNameStr) {
+ startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */);
+ }
+
+ @GuardedBy("mService")
+ final boolean startProcessLocked(ProcessRecord app,
+ String hostingType, String hostingNameStr, String abiOverride) {
+ return startProcessLocked(app, hostingType, hostingNameStr,
+ false /* disableHiddenApiChecks */, abiOverride);
+ }
+
+ @GuardedBy("mService")
+ final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
+ boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
+ boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
+ String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
+ long startTime = SystemClock.elapsedRealtime();
+ ProcessRecord app;
+ if (!isolated) {
+ app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
+ checkSlow(startTime, "startProcess: after getProcessRecord");
+
+ if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
+ // If we are in the background, then check to see if this process
+ // is bad. If so, we will just silently fail.
+ if (mService.mAppErrors.isBadProcessLocked(info)) {
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ + "/" + info.processName);
+ return null;
+ }
+ } else {
+ // When the user is explicitly starting a process, then clear its
+ // crash count so that we won't make it bad until they see at
+ // least one crash dialog again, and make the process good again
+ // if it had been bad.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ + "/" + info.processName);
+ mService.mAppErrors.resetProcessCrashTimeLocked(info);
+ if (mService.mAppErrors.isBadProcessLocked(info)) {
+ EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
+ UserHandle.getUserId(info.uid), info.uid,
+ info.processName);
+ mService.mAppErrors.clearBadProcessLocked(info);
+ if (app != null) {
+ app.bad = false;
+ }
+ }
+ }
+ } else {
+ // If this is an isolated process, it can't re-use an existing process.
+ app = null;
+ }
+
+ // We don't have to do anything more if:
+ // (1) There is an existing application record; and
+ // (2) The caller doesn't think it is dead, OR there is no thread
+ // object attached to it so we know it couldn't have crashed; and
+ // (3) There is a pid assigned to it, so it is either starting or
+ // already running.
+ if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+ + " app=" + app + " knownToBeDead=" + knownToBeDead
+ + " thread=" + (app != null ? app.thread : null)
+ + " pid=" + (app != null ? app.pid : -1));
+ if (app != null && app.pid > 0) {
+ if ((!knownToBeDead && !app.killed) || app.thread == null) {
+ // We already have the app running, or are waiting for it to
+ // come up (we have a pid but not yet its thread), so keep it.
+ if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
+ // If this is a new package in the process, add the package to the list
+ app.addPackage(info.packageName, info.versionCode, mService.mProcessStats);
+ checkSlow(startTime, "startProcess: done, added package to proc");
+ return app;
+ }
+
+ // An application record is attached to a previous process,
+ // clean it up now.
+ if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
+ checkSlow(startTime, "startProcess: bad proc running, killing");
+ ProcessList.killProcessGroup(app.uid, app.pid);
+ mService.handleAppDiedLocked(app, true, true);
+ checkSlow(startTime, "startProcess: done killing old proc");
+ }
+
+ String hostingNameStr = hostingName != null
+ ? hostingName.flattenToShortString() : null;
+
+ if (app == null) {
+ checkSlow(startTime, "startProcess: creating new process record");
+ app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
+ if (app == null) {
+ Slog.w(TAG, "Failed making new process record for "
+ + processName + "/" + info.uid + " isolated=" + isolated);
+ return null;
+ }
+ app.crashHandler = crashHandler;
+ app.isolatedEntryPoint = entryPoint;
+ app.isolatedEntryPointArgs = entryPointArgs;
+ checkSlow(startTime, "startProcess: done creating new process record");
+ } else {
+ // If this is a new package in the process, add the package to the list
+ app.addPackage(info.packageName, info.versionCode, mService.mProcessStats);
+ checkSlow(startTime, "startProcess: added package to existing proc");
+ }
+
+ // If the system is not ready yet, then hold off on starting this
+ // process until it is.
+ if (!mService.mProcessesReady
+ && !mService.isAllowedWhileBooting(info)
+ && !allowWhileBooting) {
+ if (!mService.mProcessesOnHold.contains(app)) {
+ mService.mProcessesOnHold.add(app);
+ }
+ if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
+ "System not ready, putting on hold: " + app);
+ checkSlow(startTime, "startProcess: returning with proc on hold");
+ return app;
+ }
+
+ checkSlow(startTime, "startProcess: stepping in to startProcess");
+ final boolean success = startProcessLocked(app, hostingType, hostingNameStr,
+ abiOverride);
+ checkSlow(startTime, "startProcess: done starting proc!");
+ return success ? app : null;
+ }
+
+ @GuardedBy("mService")
+ private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
+ StringBuilder sb = null;
+ if (app.killedByAm) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("killedByAm=true;");
+ }
+ if (mProcessNames.get(app.processName, app.uid) != app) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("No entry in mProcessNames;");
+ }
+ if (!app.pendingStart) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("pendingStart=false;");
+ }
+ if (app.startSeq > expectedStartSeq) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("seq=" + app.startSeq + ",expected=" + expectedStartSeq + ";");
+ }
+ return sb == null ? null : sb.toString();
+ }
+
+ @GuardedBy("mService")
+ private boolean handleProcessStartedLocked(ProcessRecord pending,
+ Process.ProcessStartResult startResult, long expectedStartSeq) {
+ // Indicates that this process start has been taken care of.
+ if (mPendingStarts.get(expectedStartSeq) == null) {
+ if (pending.pid == startResult.pid) {
+ pending.setUsingWrapper(startResult.usingWrapper);
+ // TODO: Update already existing clients of usingWrapper
+ }
+ return false;
+ }
+ return handleProcessStartedLocked(pending, startResult.pid, startResult.usingWrapper,
+ expectedStartSeq, false);
+ }
+
+ @GuardedBy("mService")
+ boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
+ long expectedStartSeq, boolean procAttached) {
+ mPendingStarts.remove(expectedStartSeq);
+ final String reason = isProcStartValidLocked(app, expectedStartSeq);
+ if (reason != null) {
+ Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" +
+ pid
+ + ", " + reason);
+ app.pendingStart = false;
+ killProcessQuiet(pid);
+ Process.killProcessGroup(app.uid, app.pid);
+ return false;
+ }
+ mService.mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
+ checkSlow(app.startTime, "startProcess: done updating battery stats");
+
+ EventLog.writeEvent(EventLogTags.AM_PROC_START,
+ UserHandle.getUserId(app.startUid), pid, app.startUid,
+ app.processName, app.hostingType,
+ app.hostingNameStr != null ? app.hostingNameStr : "");
+
+ try {
+ AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
+ app.seInfo, app.info.sourceDir, pid);
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+
+ if (app.isPersistent()) {
+ Watchdog.getInstance().processStarted(app.processName, pid);
+ }
+
+ checkSlow(app.startTime, "startProcess: building log message");
+ StringBuilder buf = mStringBuilder;
+ buf.setLength(0);
+ buf.append("Start proc ");
+ buf.append(pid);
+ buf.append(':');
+ buf.append(app.processName);
+ buf.append('/');
+ UserHandle.formatUid(buf, app.startUid);
+ if (app.isolatedEntryPoint != null) {
+ buf.append(" [");
+ buf.append(app.isolatedEntryPoint);
+ buf.append("]");
+ }
+ buf.append(" for ");
+ buf.append(app.hostingType);
+ if (app.hostingNameStr != null) {
+ buf.append(" ");
+ buf.append(app.hostingNameStr);
+ }
+ mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.startUid);
+ app.setPid(pid);
+ app.setUsingWrapper(usingWrapper);
+ app.pendingStart = false;
+ checkSlow(app.startTime, "startProcess: starting to update pids map");
+ ProcessRecord oldApp;
+ synchronized (mService.mPidsSelfLocked) {
+ oldApp = mService.mPidsSelfLocked.get(pid);
+ }
+ // If there is already an app occupying that pid that hasn't been cleaned up
+ if (oldApp != null && !app.isolated) {
+ // Clean up anything relating to this pid first
+ Slog.w(TAG, "Reusing pid " + pid
+ + " while app is still mapped to it");
+ mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+ true /*replacingPid*/);
+ }
+ synchronized (mService.mPidsSelfLocked) {
+ mService.mPidsSelfLocked.put(pid, app);
+ if (!procAttached) {
+ Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
+ msg.obj = app;
+ mService.mHandler.sendMessageDelayed(msg, usingWrapper
+ ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
+ }
+ }
+ checkSlow(app.startTime, "startProcess: done updating pids map");
+ return true;
+ }
+
+ final void removeLruProcessLocked(ProcessRecord app) {
+ int lrui = mLruProcesses.lastIndexOf(app);
+ if (lrui >= 0) {
+ if (!app.killed) {
+ if (app.isPersistent()) {
+ Slog.w(TAG, "Removing persistent process that hasn't been killed: " + app);
+ } else {
+ Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
+ if (app.pid > 0) {
+ killProcessQuiet(app.pid);
+ ProcessList.killProcessGroup(app.uid, app.pid);
+ } else {
+ app.pendingStart = false;
+ }
+ }
+ }
+ if (lrui <= mLruProcessActivityStart) {
+ mLruProcessActivityStart--;
+ }
+ if (lrui <= mLruProcessServiceStart) {
+ mLruProcessServiceStart--;
+ }
+ mLruProcesses.remove(lrui);
+ }
+ }
+
+ void killAllBackgroundProcessesLocked() {
+ final ArrayList<ProcessRecord> procs = new ArrayList<>();
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ final ProcessRecord app = apps.valueAt(ia);
+ if (app.isPersistent()) {
+ // We don't kill persistent processes.
+ continue;
+ }
+ if (app.removed) {
+ procs.add(app);
+ } else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+ }
+
+ final int N = procs.size();
+ for (int i = 0; i < N; i++) {
+ removeProcessLocked(procs.get(i), false, true, "kill all background");
+ }
+ }
+
+ @GuardedBy("mService")
+ final boolean killPackageProcessesLocked(String packageName, int appId,
+ int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
+ boolean doit, boolean evenPersistent, String reason) {
+ ArrayList<ProcessRecord> procs = new ArrayList<>();
+
+ // Remove all processes this package may have touched: all with the
+ // same UID (except for the system or root user), and all whose name
+ // matches the package name.
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ ProcessRecord app = apps.valueAt(ia);
+ if (app.isPersistent() && !evenPersistent) {
+ // we don't kill persistent processes
+ continue;
+ }
+ if (app.removed) {
+ if (doit) {
+ procs.add(app);
+ }
+ continue;
+ }
+
+ // Skip process if it doesn't meet our oom adj requirement.
+ if (app.setAdj < minOomAdj) {
+ continue;
+ }
+
+ // If no package is specified, we call all processes under the
+ // give user id.
+ if (packageName == null) {
+ if (userId != UserHandle.USER_ALL && app.userId != userId) {
+ continue;
+ }
+ if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
+ continue;
+ }
+ // Package has been specified, we want to hit all processes
+ // that match it. We need to qualify this by the processes
+ // that are running under the specified app and user ID.
+ } else {
+ final boolean isDep = app.pkgDeps != null
+ && app.pkgDeps.contains(packageName);
+ if (!isDep && UserHandle.getAppId(app.uid) != appId) {
+ continue;
+ }
+ if (userId != UserHandle.USER_ALL && app.userId != userId) {
+ continue;
+ }
+ if (!app.pkgList.containsKey(packageName) && !isDep) {
+ continue;
+ }
+ }
+
+ // Process has passed all conditions, kill it!
+ if (!doit) {
+ return true;
+ }
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+
+ int N = procs.size();
+ for (int i=0; i<N; i++) {
+ removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
+ }
+ mService.updateOomAdjLocked();
+ return N > 0;
+ }
+ @GuardedBy("mService")
+ boolean removeProcessLocked(ProcessRecord app,
+ boolean callerWillRestart, boolean allowRestart, String reason) {
+ final String name = app.processName;
+ final int uid = app.uid;
+ if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES,
+ "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")");
+
+ ProcessRecord old = mProcessNames.get(name, uid);
+ if (old != app) {
+ // This process is no longer active, so nothing to do.
+ Slog.w(TAG, "Ignoring remove of inactive process: " + app);
+ return false;
+ }
+ removeProcessNameLocked(name, uid);
+ mService.mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
+
+ boolean needRestart = false;
+ if ((app.pid > 0 && app.pid != ActivityManagerService.MY_PID) || (app.pid == 0 && app
+ .pendingStart)) {
+ int pid = app.pid;
+ if (pid > 0) {
+ synchronized (mService.mPidsSelfLocked) {
+ mService.mPidsSelfLocked.remove(pid);
+ mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+ }
+ mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
+ if (app.isolated) {
+ mService.mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ mService.getPackageManagerInternalLocked().removeIsolatedUid(app.uid);
+ }
+ }
+ boolean willRestart = false;
+ if (app.isPersistent() && !app.isolated) {
+ if (!callerWillRestart) {
+ willRestart = true;
+ } else {
+ needRestart = true;
+ }
+ }
+ app.kill(reason, true);
+ mService.handleAppDiedLocked(app, willRestart, allowRestart);
+ if (willRestart) {
+ removeLruProcessLocked(app);
+ mService.addAppLocked(app.info, null, false, null /* ABI override */);
+ }
+ } else {
+ mRemovedProcesses.add(app);
+ }
+
+ return needRestart;
+ }
+
+ @GuardedBy("mService")
+ final void addProcessNameLocked(ProcessRecord proc) {
+ // We shouldn't already have a process under this name, but just in case we
+ // need to clean up whatever may be there now.
+ ProcessRecord old = removeProcessNameLocked(proc.processName, proc.uid);
+ if (old == proc && proc.isPersistent()) {
+ // We are re-adding a persistent process. Whatevs! Just leave it there.
+ Slog.w(TAG, "Re-adding persistent process " + proc);
+ } else if (old != null) {
+ Slog.wtf(TAG, "Already have existing proc " + old + " when adding " + proc);
+ }
+ UidRecord uidRec = mService.mActiveUids.get(proc.uid);
+ if (uidRec == null) {
+ uidRec = new UidRecord(proc.uid);
+ // This is the first appearance of the uid, report it now!
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "Creating new process uid: " + uidRec);
+ if (Arrays.binarySearch(mService.mDeviceIdleTempWhitelist,
+ UserHandle.getAppId(proc.uid)) >= 0
+ || mService.mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) {
+ uidRec.setWhitelist = uidRec.curWhitelist = true;
+ }
+ uidRec.updateHasInternetPermission();
+ mService.mActiveUids.put(proc.uid, uidRec);
+ EventLogTags.writeAmUidRunning(uidRec.uid);
+ mService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
+ }
+ proc.uidRecord = uidRec;
+
+ // Reset render thread tid if it was already set, so new process can set it again.
+ proc.renderThreadTid = 0;
+ uidRec.numProcs++;
+ mProcessNames.put(proc.processName, proc.uid, proc);
+ if (proc.isolated) {
+ mIsolatedProcesses.put(proc.uid, proc);
+ }
+ }
+
+ @GuardedBy("mService")
+ final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
+ boolean isolated, int isolatedUid) {
+ String proc = customProcess != null ? customProcess : info.processName;
+ final int userId = UserHandle.getUserId(info.uid);
+ int uid = info.uid;
+ if (isolated) {
+ if (isolatedUid == 0) {
+ int stepsLeft = LAST_ISOLATED_UID - FIRST_ISOLATED_UID + 1;
+ while (true) {
+ if (mNextIsolatedProcessUid < FIRST_ISOLATED_UID
+ || mNextIsolatedProcessUid > LAST_ISOLATED_UID) {
+ mNextIsolatedProcessUid = FIRST_ISOLATED_UID;
+ }
+ uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
+ mNextIsolatedProcessUid++;
+ if (mIsolatedProcesses.indexOfKey(uid) < 0) {
+ // No process for this uid, use it.
+ break;
+ }
+ stepsLeft--;
+ if (stepsLeft <= 0) {
+ return null;
+ }
+ }
+ } else {
+ // Special case for startIsolatedProcess (internal only), where
+ // the uid of the isolated process is specified by the caller.
+ uid = isolatedUid;
+ }
+ mService.getPackageManagerInternalLocked().addIsolatedUid(uid, info.uid);
+
+ // Register the isolated UID with this application so BatteryStats knows to
+ // attribute resource usage to the application.
+ //
+ // NOTE: This is done here before addProcessNameLocked, which will tell BatteryStats
+ // about the process state of the isolated UID *before* it is registered with the
+ // owning application.
+ mService.mBatteryStatsService.addIsolatedUid(uid, info.uid);
+ StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
+ StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
+ }
+ final ProcessRecord r = new ProcessRecord(mService, info, proc, uid,
+ mService.getGlobalConfiguration());
+
+ if (!mService.mBooted && !mService.mBooting
+ && userId == UserHandle.USER_SYSTEM
+ && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+ // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
+ r.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
+ r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ r.setPersistent(true);
+ r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
+ }
+ if (isolated && isolatedUid != 0) {
+ // Special case for startIsolatedProcess (internal only) - assume the process
+ // is required by the system server to prevent it being killed.
+ r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
+ }
+ addProcessNameLocked(r);
+ return r;
+ }
+
+ @GuardedBy("mService")
+ final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
+ return removeProcessNameLocked(name, uid, null);
+ }
+
+ @GuardedBy("mService")
+ final ProcessRecord removeProcessNameLocked(final String name, final int uid,
+ final ProcessRecord expecting) {
+ ProcessRecord old = mProcessNames.get(name, uid);
+ // Only actually remove when the currently recorded value matches the
+ // record that we expected; if it doesn't match then we raced with a
+ // newly created process and we don't want to destroy the new one.
+ if ((expecting == null) || (old == expecting)) {
+ mProcessNames.remove(name, uid);
+ }
+ if (old != null && old.uidRecord != null) {
+ old.uidRecord.numProcs--;
+ if (old.uidRecord.numProcs == 0) {
+ // No more processes using this uid, tell clients it is gone.
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
+ "No more processes in " + old.uidRecord);
+ mService.enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
+ EventLogTags.writeAmUidStopped(uid);
+ mService.mActiveUids.remove(uid);
+ mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
+ }
+ old.uidRecord = null;
+ }
+ mIsolatedProcesses.remove(uid);
+ return old;
+ }
+
+ /** Call setCoreSettings on all LRU processes, with the new settings. */
+ @GuardedBy("mService")
+ void updateCoreSettingsLocked(Bundle settings) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord processRecord = mLruProcesses.get(i);
+ try {
+ if (processRecord.thread != null) {
+ processRecord.thread.setCoreSettings(settings);
+ }
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+ }
+
+ /**
+ * Kill all background processes except for ones with targetSdk lower than minTargetSdk and
+ * procstate lower than maxProcState.
+ * @param minTargetSdk
+ * @param maxProcState
+ */
+ @GuardedBy("mService")
+ void killAllBackgroundProcessesExceptLocked(int minTargetSdk, int maxProcState) {
+ final ArrayList<ProcessRecord> procs = new ArrayList<>();
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ final ProcessRecord app = apps.valueAt(ia);
+ if (app.removed) {
+ procs.add(app);
+ } else if ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
+ && (maxProcState < 0 || app.setProcState > maxProcState)) {
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+ }
+
+ final int N = procs.size();
+ for (int i = 0; i < N; i++) {
+ removeProcessLocked(procs.get(i), false, true, "kill all background except");
+ }
+ }
+
+ /**
+ * Call updateTimePrefs on all LRU processes
+ * @param timePref The time pref to pass to each process
+ */
+ @GuardedBy("mService")
+ void updateAllTimePrefsLocked(int timePref) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null) {
+ try {
+ r.thread.updateTimePrefs(timePref);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to update preferences for: "
+ + r.info.processName);
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void setAllHttpProxyLocked(String host, String port, String exclList, Uri pacFileUrl) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ // Don't dispatch to isolated processes as they can't access
+ // ConnectivityManager and don't have network privileges anyway.
+ if (r.thread != null && !r.isolated) {
+ try {
+ r.thread.setHttpProxy(host, port, exclList, pacFileUrl);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to update http proxy for: " +
+ r.info.processName);
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void clearAllDnsCacheLocked() {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null) {
+ try {
+ r.thread.clearDnsCache();
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void handleAllTrustStorageUpdateLocked() {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null) {
+ try {
+ r.thread.handleTrustStorageUpdate();
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to handle trust storage update for: " +
+ r.info.processName);
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
+ String what, Object obj, ProcessRecord srcApp) {
+ app.lastActivityTime = now;
+
+ if (app.hasActivitiesOrRecentTasks()) {
+ // Don't want to touch dependent processes that are hosting activities.
+ return index;
+ }
+
+ int lrui = mLruProcesses.lastIndexOf(app);
+ if (lrui < 0) {
+ Slog.wtf(TAG, "Adding dependent process " + app + " not on LRU list: "
+ + what + " " + obj + " from " + srcApp);
+ return index;
+ }
+
+ if (lrui >= index) {
+ // Don't want to cause this to move dependent processes *back* in the
+ // list as if they were less frequently used.
+ return index;
+ }
+
+ if (lrui >= mLruProcessActivityStart) {
+ // Don't want to touch dependent processes that are hosting activities.
+ return index;
+ }
+
+ mLruProcesses.remove(lrui);
+ if (index > 0) {
+ index--;
+ }
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Moving dep from " + lrui + " to " + index
+ + " in LRU list: " + app);
+ mLruProcesses.add(index, app);
+ return index;
+ }
+
+ final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
+ ProcessRecord client) {
+ final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities()
+ || app.treatLikeActivity;
+ final boolean hasService = false; // not impl yet. app.services.size() > 0;
+ if (!activityChange && hasActivity) {
+ // The process has activities, so we are only allowing activity-based adjustments
+ // to move it. It should be kept in the front of the list with other
+ // processes that have activities, and we don't want those to change their
+ // order except due to activity operations.
+ return;
+ }
+
+ mLruSeq++;
+ final long now = SystemClock.uptimeMillis();
+ app.lastActivityTime = now;
+
+ // First a quick reject: if the app is already at the position we will
+ // put it, then there is nothing to do.
+ if (hasActivity) {
+ final int N = mLruProcesses.size();
+ if (N > 0 && mLruProcesses.get(N - 1) == app) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top activity: " + app);
+ return;
+ }
+ } else {
+ if (mLruProcessServiceStart > 0
+ && mLruProcesses.get(mLruProcessServiceStart-1) == app) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, already top other: " + app);
+ return;
+ }
+ }
+
+ int lrui = mLruProcesses.lastIndexOf(app);
+
+ if (app.isPersistent() && lrui >= 0) {
+ // We don't care about the position of persistent processes, as long as
+ // they are in the list.
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, persistent: " + app);
+ return;
+ }
+
+ /* In progress: compute new position first, so we can avoid doing work
+ if the process is not actually going to move. Not yet working.
+ int addIndex;
+ int nextIndex;
+ boolean inActivity = false, inService = false;
+ if (hasActivity) {
+ // Process has activities, put it at the very tipsy-top.
+ addIndex = mLruProcesses.size();
+ nextIndex = mLruProcessServiceStart;
+ inActivity = true;
+ } else if (hasService) {
+ // Process has services, put it at the top of the service list.
+ addIndex = mLruProcessActivityStart;
+ nextIndex = mLruProcessServiceStart;
+ inActivity = true;
+ inService = true;
+ } else {
+ // Process not otherwise of interest, it goes to the top of the non-service area.
+ addIndex = mLruProcessServiceStart;
+ if (client != null) {
+ int clientIndex = mLruProcesses.lastIndexOf(client);
+ if (clientIndex < 0) Slog.d(TAG, "Unknown client " + client + " when updating "
+ + app);
+ if (clientIndex >= 0 && addIndex > clientIndex) {
+ addIndex = clientIndex;
+ }
+ }
+ nextIndex = addIndex > 0 ? addIndex-1 : addIndex;
+ }
+
+ Slog.d(TAG, "Update LRU at " + lrui + " to " + addIndex + " (act="
+ + mLruProcessActivityStart + "): " + app);
+ */
+
+ if (lrui >= 0) {
+ if (lrui < mLruProcessActivityStart) {
+ mLruProcessActivityStart--;
+ }
+ if (lrui < mLruProcessServiceStart) {
+ mLruProcessServiceStart--;
+ }
+ /*
+ if (addIndex > lrui) {
+ addIndex--;
+ }
+ if (nextIndex > lrui) {
+ nextIndex--;
+ }
+ */
+ mLruProcesses.remove(lrui);
+ }
+
+ /*
+ mLruProcesses.add(addIndex, app);
+ if (inActivity) {
+ mLruProcessActivityStart++;
+ }
+ if (inService) {
+ mLruProcessActivityStart++;
+ }
+ */
+
+ int nextIndex;
+ if (hasActivity) {
+ final int N = mLruProcesses.size();
+ if ((!app.hasActivities() || app.hasRecentTasks())
+ && mLruProcessActivityStart < (N - 1)) {
+ // Process doesn't have activities, but has clients with
+ // activities... move it up, but one below the top (the top
+ // should always have a real activity).
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Adding to second-top of LRU activity list: " + app);
+ mLruProcesses.add(N - 1, app);
+ // To keep it from spamming the LRU list (by making a bunch of clients),
+ // we will push down any other entries owned by the app.
+ final int uid = app.info.uid;
+ for (int i = N - 2; i > mLruProcessActivityStart; i--) {
+ ProcessRecord subProc = mLruProcesses.get(i);
+ if (subProc.info.uid == uid) {
+ // We want to push this one down the list. If the process after
+ // it is for the same uid, however, don't do so, because we don't
+ // want them internally to be re-ordered.
+ if (mLruProcesses.get(i - 1).info.uid != uid) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Pushing uid " + uid + " swapping at " + i + ": "
+ + mLruProcesses.get(i) + " : "
+ + mLruProcesses.get(i - 1));
+ ProcessRecord tmp = mLruProcesses.get(i);
+ mLruProcesses.set(i, mLruProcesses.get(i - 1));
+ mLruProcesses.set(i - 1, tmp);
+ i--;
+ }
+ } else {
+ // A gap, we can stop here.
+ break;
+ }
+ }
+ } else {
+ // Process has activities, put it at the very tipsy-top.
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU activity list: " + app);
+ mLruProcesses.add(app);
+ }
+ nextIndex = mLruProcessServiceStart;
+ } else if (hasService) {
+ // Process has services, put it at the top of the service list.
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU service list: " + app);
+ mLruProcesses.add(mLruProcessActivityStart, app);
+ nextIndex = mLruProcessServiceStart;
+ mLruProcessActivityStart++;
+ } else {
+ // Process not otherwise of interest, it goes to the top of the non-service area.
+ int index = mLruProcessServiceStart;
+ if (client != null) {
+ // If there is a client, don't allow the process to be moved up higher
+ // in the list than that client.
+ int clientIndex = mLruProcesses.lastIndexOf(client);
+ if (DEBUG_LRU && clientIndex < 0) Slog.d(TAG_LRU, "Unknown client " + client
+ + " when updating " + app);
+ if (clientIndex <= lrui) {
+ // Don't allow the client index restriction to push it down farther in the
+ // list than it already is.
+ clientIndex = lrui;
+ }
+ if (clientIndex >= 0 && index > clientIndex) {
+ index = clientIndex;
+ }
+ }
+ if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding at " + index + " of LRU list: " + app);
+ mLruProcesses.add(index, app);
+ nextIndex = index - 1;
+ mLruProcessActivityStart++;
+ mLruProcessServiceStart++;
+ }
+
+ // If the app is currently using a content provider or service,
+ // bump those processes as well.
+ for (int j = app.connections.size() - 1; j >= 0; j--) {
+ ConnectionRecord cr = app.connections.valueAt(j);
+ if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
+ && cr.binding.service.app != null
+ && cr.binding.service.app.lruSeq != mLruSeq
+ && !cr.binding.service.app.isPersistent()) {
+ nextIndex = updateLruProcessInternalLocked(cr.binding.service.app,
+ now,
+ nextIndex,
+ "service connection", cr, app);
+ }
+ }
+ for (int j = app.conProviders.size() - 1; j >= 0; j--) {
+ ContentProviderRecord cpr = app.conProviders.get(j).provider;
+ if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.isPersistent()) {
+ nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
+ "provider reference", cpr, app);
+ }
+ }
+ }
+
+ final ProcessRecord getLRURecordForAppLocked(IApplicationThread thread) {
+ final IBinder threadBinder = thread.asBinder();
+ // Find the application record.
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ final ProcessRecord rec = mLruProcesses.get(i);
+ if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
+ return rec;
+ }
+ }
+ return null;
+ }
+
+ boolean haveBackgroundProcessLocked() {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ final ProcessRecord rec = mLruProcesses.get(i);
+ if (rec.thread != null
+ && rec.setProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static int procStateToImportance(int procState, int memAdj,
+ ActivityManager.RunningAppProcessInfo currApp,
+ int clientTargetSdk) {
+ int imp = ActivityManager.RunningAppProcessInfo.procStateToImportanceForTargetSdk(
+ procState, clientTargetSdk);
+ if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
+ currApp.lru = memAdj;
+ } else {
+ currApp.lru = 0;
+ }
+ return imp;
+ }
+
+ @GuardedBy("mService")
+ void fillInProcMemInfoLocked(ProcessRecord app,
+ ActivityManager.RunningAppProcessInfo outInfo,
+ int clientTargetSdk) {
+ outInfo.pid = app.pid;
+ outInfo.uid = app.info.uid;
+ if (mService.mAtmInternal.isHeavyWeightProcess(app.getWindowProcessController())) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
+ }
+ if (app.isPersistent()) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
+ }
+ if (app.hasActivities()) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
+ }
+ outInfo.lastTrimLevel = app.trimMemoryLevel;
+ int adj = app.curAdj;
+ int procState = app.getCurProcState();
+ outInfo.importance = procStateToImportance(procState, adj, outInfo,
+ clientTargetSdk);
+ outInfo.importanceReasonCode = app.adjTypeCode;
+ outInfo.processState = app.getCurProcState();
+ outInfo.isFocused = (app == mService.getTopAppLocked());
+ outInfo.lastActivityTime = app.lastActivityTime;
+ }
+
+ @GuardedBy("mService")
+ List<ActivityManager.RunningAppProcessInfo> getRunningAppProcessesLocked(boolean allUsers,
+ int userId, boolean allUids, int callingUid, int clientTargetSdk) {
+ // Lazy instantiation of list
+ List<ActivityManager.RunningAppProcessInfo> runList = null;
+
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord app = mLruProcesses.get(i);
+ if ((!allUsers && app.userId != userId)
+ || (!allUids && app.uid != callingUid)) {
+ continue;
+ }
+ if ((app.thread != null) && (!app.isCrashing() && !app.isNotResponding())) {
+ // Generate process state info for running application
+ ActivityManager.RunningAppProcessInfo currApp =
+ new ActivityManager.RunningAppProcessInfo(app.processName,
+ app.pid, app.getPackageList());
+ fillInProcMemInfoLocked(app, currApp, clientTargetSdk);
+ if (app.adjSource instanceof ProcessRecord) {
+ currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+ currApp.importanceReasonImportance =
+ ActivityManager.RunningAppProcessInfo.procStateToImportance(
+ app.adjSourceProcState);
+ } else if (app.adjSource instanceof ActivityRecord) {
+ ActivityRecord r = (ActivityRecord)app.adjSource;
+ if (r.app != null) currApp.importanceReasonPid = r.app.getPid();
+ }
+ if (app.adjTarget instanceof ComponentName) {
+ currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
+ }
+ //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
+ // + " lru=" + currApp.lru);
+ if (runList == null) {
+ runList = new ArrayList<>();
+ }
+ runList.add(currApp);
+ }
+ }
+ return runList;
+ }
+
+ @GuardedBy("mService")
+ int getLruSizeLocked() {
+ return mLruProcesses.size();
+ }
+
+ @GuardedBy("mService")
+ void dumpLruListHeaderLocked(PrintWriter pw) {
+ pw.print(" Process LRU list (sorted by oom_adj, "); pw.print(mLruProcesses.size());
+ pw.print(" total, non-act at ");
+ pw.print(mLruProcesses.size() - mLruProcessActivityStart);
+ pw.print(", non-svc at ");
+ pw.print(mLruProcesses.size() - mLruProcessServiceStart);
+ pw.println("):");
+ }
+
+ @GuardedBy("mService")
+ ArrayList<ProcessRecord> collectProcessesLocked(int start, boolean allPkgs, String[] args) {
+ ArrayList<ProcessRecord> procs;
+ if (args != null && args.length > start
+ && args[start].charAt(0) != '-') {
+ procs = new ArrayList<ProcessRecord>();
+ int pid = -1;
+ try {
+ pid = Integer.parseInt(args[start]);
+ } catch (NumberFormatException e) {
+ }
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord proc = mLruProcesses.get(i);
+ if (proc.pid > 0 && proc.pid == pid) {
+ procs.add(proc);
+ } else if (allPkgs && proc.pkgList != null
+ && proc.pkgList.containsKey(args[start])) {
+ procs.add(proc);
+ } else if (proc.processName.equals(args[start])) {
+ procs.add(proc);
+ }
+ }
+ if (procs.size() <= 0) {
+ return null;
+ }
+ } else {
+ procs = new ArrayList<ProcessRecord>(mLruProcesses);
+ }
+ return procs;
+ }
+
+ @GuardedBy("mService")
+ void updateApplicationInfoLocked(List<String> packagesToUpdate, int userId,
+ boolean updateFrameworkRes) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ final ProcessRecord app = mLruProcesses.get(i);
+ if (app.thread == null) {
+ continue;
+ }
+
+ if (userId != UserHandle.USER_ALL && app.userId != userId) {
+ continue;
+ }
+
+ final int packageCount = app.pkgList.size();
+ for (int j = 0; j < packageCount; j++) {
+ final String packageName = app.pkgList.keyAt(j);
+ if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
+ try {
+ final ApplicationInfo ai = AppGlobals.getPackageManager()
+ .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);
+ if (ai != null) {
+ app.thread.scheduleApplicationInfoChanged(ai);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",
+ packageName, app));
+ }
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
+ try {
+ r.thread.dispatchPackageBroadcast(cmd, packages);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0eb535b74d13..fa7a08bb12eb 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -28,6 +28,7 @@ import android.app.ActivityManager;
import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IApplicationThread;
+import android.app.ProfilerInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -60,6 +61,7 @@ import com.android.internal.os.ProcessCpuTracker;
import com.android.server.Watchdog;
import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -733,7 +735,7 @@ final class ProcessRecord implements WindowProcessListener {
if (pid > 0) {
EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
Process.killProcessQuiet(pid);
- ActivityManagerService.killProcessGroup(uid, pid);
+ ProcessList.killProcessGroup(uid, pid);
} else {
pendingStart = false;
}
@@ -836,6 +838,13 @@ final class ProcessRecord implements WindowProcessListener {
return null;
}
+ @Override
+ public void addPackage(String pkg, long versionCode) {
+ synchronized (mService) {
+ addPackage(pkg, versionCode, mService.mProcessStats);
+ }
+ }
+
/*
* Return true if package has been added false if not
*/
@@ -1157,7 +1166,7 @@ final class ProcessRecord implements WindowProcessListener {
mService.mServices.updateServiceConnectionActivitiesLocked(this);
}
if (updateLru) {
- mService.updateLruProcessLocked(this, activityChange, null);
+ mService.mProcessList.updateLruProcessLocked(this, activityChange, null);
}
if (updateOomAdj) {
mService.updateOomAdjLocked();
@@ -1176,10 +1185,55 @@ final class ProcessRecord implements WindowProcessListener {
* Returns the total time (in milliseconds) spent executing in both user and system code.
* Safe to call without lock held.
*/
+ @Override
public long getCpuTime() {
return mService.mProcessCpuTracker.getCpuTimeForPid(pid);
}
+ @Override
+ public void clearWaitingToKill() {
+ synchronized (mService) {
+ waitingToKill = null;
+ }
+ }
+
+ @Override
+ public ProfilerInfo onStartActivity(int topProcessState) {
+ synchronized (mService) {
+ ProfilerInfo profilerInfo = null;
+ if (mService.mProfileApp != null && mService.mProfileApp.equals(processName)) {
+ if (mService.mProfileProc == null || mService.mProfileProc == this) {
+ mService.mProfileProc = this;
+ final ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
+ if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
+ if (profilerInfoSvc.profileFd != null) {
+ try {
+ profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
+ } catch (IOException e) {
+ profilerInfoSvc.closeFd();
+ }
+ }
+
+ profilerInfo = new ProfilerInfo(profilerInfoSvc);
+ }
+ }
+ }
+
+ hasShownUi = true;
+ setPendingUiClean(true);
+ forceProcessStateUpTo(topProcessState);
+
+ return profilerInfo;
+ }
+ }
+
+ @Override
+ public void appDied() {
+ synchronized (mService) {
+ mService.appDiedLocked(this);
+ }
+ }
+
public long getInputDispatchingTimeout() {
return mWindowProcessController.getInputDispatchingTimeout();
}
@@ -1256,8 +1310,8 @@ final class ProcessRecord implements WindowProcessListener {
if (MY_PID != pid && MY_PID != parentPid) firstPids.add(MY_PID);
- for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord r = mService.mLruProcesses.get(i);
+ for (int i = mService.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mService.mProcessList.mLruProcesses.get(i);
if (r != null && r.thread != null) {
int myPid = r.pid;
if (myPid > 0 && myPid != pid && myPid != parentPid && myPid != MY_PID) {
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 792b66be6dd9..1743ddeedd91 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -37,6 +37,7 @@ import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_N
import android.app.Activity;
import android.app.ActivityThread;
import android.app.IApplicationThread;
+import android.app.ProfilerInfo;
import android.app.servertransaction.ConfigurationChangeItem;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -674,6 +675,35 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mAtm.mH.sendMessage(m);
}
+ void clearWaitingToKill() {
+ if (mListener == null) return;
+ // Posting on handler so WM lock isn't held when we call into AM.
+ final Message m = PooledLambda.obtainMessage(
+ WindowProcessListener::clearWaitingToKill, mListener);
+ mAtm.mH.sendMessage(m);
+ }
+
+ void addPackage(String pkg, long versionCode) {
+ // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
+ // using WM lock. Need to figure-out if it is okay to do this asynchronously.
+ if (mListener == null) return;
+ mListener.addPackage(pkg, versionCode);
+ }
+
+ ProfilerInfo onStartActivity(int topProcessState) {
+ // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
+ // using WM lock. Need to figure-out if it is okay to do this asynchronously.
+ if (mListener == null) return null;
+ return mListener.onStartActivity(topProcessState);
+ }
+
+ public void appDied() {
+ // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
+ // using WM lock. Need to figure-out if it is okay to do this asynchronously.
+ if (mListener == null) return;
+ mListener.appDied();
+ }
+
@Override
public void onConfigurationChanged(Configuration newGlobalConfig) {
super.onConfigurationChanged(newGlobalConfig);
diff --git a/services/core/java/com/android/server/am/WindowProcessListener.java b/services/core/java/com/android/server/am/WindowProcessListener.java
index 9cad6fe47563..4a7e6e8a38fe 100644
--- a/services/core/java/com/android/server/am/WindowProcessListener.java
+++ b/services/core/java/com/android/server/am/WindowProcessListener.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.app.ProfilerInfo;
import android.content.pm.ApplicationInfo;
import android.util.proto.ProtoOutputStream;
@@ -51,5 +52,16 @@ public interface WindowProcessListener {
/** Returns the total time (in milliseconds) spent executing in both user and system code. */
long getCpuTime();
+ /** Clears the waiting to kill reason for this process. */
+ void clearWaitingToKill();
+
+ /** Adds the package to the process. */
+ void addPackage(String pkg, long versionCode);
+
+ /** Called when we are in the process on starting an activity. */
+ ProfilerInfo onStartActivity(int topProcessState);
+
+ /** App died :(...oh well */
+ void appDied();
void writeToProto(ProtoOutputStream proto, long fieldId);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index fc76b46f5dcf..d57214ea894c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -109,10 +109,12 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionInspector;
+import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -129,6 +131,9 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.InputMethodDebug;
+import com.android.internal.inputmethod.StartInputReason;
+import com.android.internal.inputmethod.UnbindReason;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.HandlerCaller;
@@ -144,7 +149,6 @@ import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.IInputSessionCallback;
import com.android.internal.view.InputBindResult;
-import com.android.internal.view.InputMethodClient;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -500,6 +504,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*
* @see #mCurFocusedWindow
*/
+ @SoftInputModeFlags
int mCurFocusedWindowSoftInputMode;
/**
@@ -517,6 +522,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*
* @see android.view.inputmethod.InputConnectionInspector.MissingMethodFlags
*/
+ @MissingMethodFlags
int mCurInputContextMissingMethods;
/**
@@ -690,20 +696,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final IBinder mImeToken;
@NonNull
final String mImeId;
- // @InputMethodClient.StartInputReason
+ @StartInputReason
final int mStartInputReason;
final boolean mRestarting;
@Nullable
final IBinder mTargetWindow;
@NonNull
final EditorInfo mEditorInfo;
+ @SoftInputModeFlags
final int mTargetWindowSoftInputMode;
final int mClientBindSequenceNumber;
StartInputInfo(@NonNull IBinder imeToken, @NonNull String imeId,
- /* @InputMethodClient.StartInputReason */ int startInputReason, boolean restarting,
+ @StartInputReason int startInputReason, boolean restarting,
@Nullable IBinder targetWindow, @NonNull EditorInfo editorInfo,
- int targetWindowSoftInputMode, int clientBindSequenceNumber) {
+ @SoftInputModeFlags int targetWindowSoftInputMode, int clientBindSequenceNumber) {
mSequenceNumber = sSequenceNumber.getAndIncrement();
mTimestamp = SystemClock.uptimeMillis();
mWallTime = System.currentTimeMillis();
@@ -771,13 +778,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
String mImeTokenString;
@NonNull
String mImeId;
- /* @InputMethodClient.StartInputReason */
+ @StartInputReason
int mStartInputReason;
boolean mRestarting;
@NonNull
String mTargetWindowString;
@NonNull
EditorInfo mEditorInfo;
+ @SoftInputModeFlags
int mTargetWindowSoftInputMode;
int mClientBindSequenceNumber;
@@ -834,7 +842,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
pw.println(" time=" + dataFormat.format(new Date(entry.mWallTime))
+ " (timestamp=" + entry.mTimestamp + ")"
+ " reason="
- + InputMethodClient.getStartInputReason(entry.mStartInputReason)
+ + InputMethodDebug.startInputReasonToString(entry.mStartInputReason)
+ " restarting=" + entry.mRestarting);
pw.print(prefix);
@@ -846,7 +854,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ " clientBindSeq=" + entry.mClientBindSequenceNumber);
pw.print(prefix);
- pw.println(" softInputMode=" + InputMethodClient.softInputModeToString(
+ pw.println(" softInputMode=" + InputMethodDebug.softInputModeToString(
entry.mTargetWindowSoftInputMode));
pw.print(prefix);
@@ -1499,7 +1507,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// TODO: Is it really possible that switchUserLocked() happens before system ready?
if (mSystemReady) {
hideCurrentInputLocked(0, null);
- resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_SWITCH_USER);
+ resetCurrentMethodAndClient(UnbindReason.SWITCH_USER);
buildInputMethodListLocked(initialUserSwitch);
if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) {
// This is the first time of the user switch and
@@ -1729,7 +1737,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
* {@link InputMethodManagerService}.
*
* <p>As a general principle, IPCs from the application process that take
- * {@link InputMethodClient} will be rejected without this step.</p>
+ * {@link IInputMethodClient} will be rejected without this step.</p>
*
* @param client {@link android.os.Binder} proxy that is associated with the singleton instance
* of {@link android.view.inputmethod.InputMethodManager} that runs on the client
@@ -1808,8 +1816,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- void unbindCurrentClientLocked(
- /* @InputMethodClient.UnbindReason */ final int unbindClientReason) {
+ void unbindCurrentClientLocked(@UnbindReason int unbindClientReason) {
if (mCurClient != null) {
if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client="
+ mCurClient.client.asBinder());
@@ -1855,8 +1862,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("mMethodMap")
@NonNull
- InputBindResult attachNewInputLocked(
- /* @InputMethodClient.StartInputReason */ final int startInputReason, boolean initial) {
+ InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
if (!mBoundToMethod) {
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
@@ -1886,9 +1892,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("mMethodMap")
@NonNull
InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
- /* @InputConnectionInspector.missingMethods */ final int missingMethods,
- @NonNull EditorInfo attribute, int controlFlags,
- /* @InputMethodClient.StartInputReason */ final int startInputReason) {
+ @MissingMethodFlags int missingMethods, @NonNull EditorInfo attribute, int controlFlags,
+ @StartInputReason int startInputReason) {
// If no method is currently selected, do nothing.
if (mCurMethodId == null) {
return InputBindResult.NO_IME;
@@ -1921,7 +1926,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurClientInKeyguard = isKeyguardLocked();
// If the client is changing, we need to switch over to the new
// one.
- unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_CLIENT);
+ unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT);
if (DEBUG) Slog.v(TAG, "switching to client: client="
+ cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
@@ -2046,7 +2051,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurClient.curSession = new SessionState(mCurClient,
method, session, channel);
InputBindResult res = attachNewInputLocked(
- InputMethodClient.START_INPUT_REASON_SESSION_CREATED_BY_IME, true);
+ StartInputReason.SESSION_CREATED_BY_IME, true);
if (res.method != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
MSG_BIND_CLIENT, mCurClient.client, res));
@@ -2088,8 +2093,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
clearCurMethodLocked();
}
- void resetCurrentMethodAndClient(
- /* @InputMethodClient.UnbindReason */ final int unbindClientReason) {
+ void resetCurrentMethodAndClient(@UnbindReason int unbindClientReason) {
mCurMethodId = null;
unbindCurrentMethodLocked();
unbindCurrentClientLocked(unbindClientReason);
@@ -2166,7 +2170,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mLastBindTime = SystemClock.uptimeMillis();
mShowRequested = mInputShown;
mInputShown = false;
- unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_DISCONNECT_IME);
+ unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
}
}
}
@@ -2477,12 +2481,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Unknown input method from prefs: " + id, e);
- resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_SWITCH_IME_FAILED);
+ resetCurrentMethodAndClient(UnbindReason.SWITCH_IME_FAILED);
}
mShortcutInputMethodsAndSubtypes.clear();
} else {
// There is no longer an input method set, so stop any current one.
- resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_NO_IME);
+ resetCurrentMethodAndClient(UnbindReason.NO_IME);
}
// Here is not the perfect place to reset the switching controller. Ideally
// mSwitchingController and mSettings should be able to share the same state.
@@ -2560,7 +2564,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
intent.putExtra("input_method_id", id);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
- unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_IME);
+ unbindCurrentClientLocked(UnbindReason.SWITCH_IME);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2734,11 +2738,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@NonNull
@Override
public InputBindResult startInputOrWindowGainedFocus(
- /* @InputMethodClient.StartInputReason */ final int startInputReason,
- IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
- int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.missingMethods */ final int missingMethods,
- int unverifiedTargetSdkVersion) {
+ @StartInputReason int startInputReason, IInputMethodClient client, IBinder windowToken,
+ int controlFlags, @SoftInputModeFlags int softInputMode, int windowFlags,
+ @Nullable EditorInfo attribute, IInputContext inputContext,
+ @MissingMethodFlags int missingMethods, int unverifiedTargetSdkVersion) {
if (windowToken == null) {
Slog.e(TAG, "windowToken cannot be null.");
return InputBindResult.NULL;
@@ -2749,7 +2752,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (result == null) {
// This must never happen, but just in case.
Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason="
- + InputMethodClient.getStartInputReason(startInputReason)
+ + InputMethodDebug.startInputReasonToString(startInputReason)
+ " windowFlags=#" + Integer.toHexString(windowFlags)
+ " editorInfo=" + attribute);
return InputBindResult.NULL;
@@ -2759,12 +2762,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@NonNull
private InputBindResult startInputOrWindowGainedFocusInternal(
- /* @InputMethodClient.StartInputReason */ final int startInputReason,
- IInputMethodClient client, @NonNull IBinder windowToken, int controlFlags,
- /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
+ @StartInputReason int startInputReason, IInputMethodClient client,
+ @NonNull IBinder windowToken, int controlFlags, @SoftInputModeFlags int softInputMode,
int windowFlags, EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.missingMethods */ final int missingMethods,
- int unverifiedTargetSdkVersion) {
+ @MissingMethodFlags int missingMethods, int unverifiedTargetSdkVersion) {
// Needs to check the validity before clearing calling identity
final boolean calledFromValidUser = calledFromValidUser();
InputBindResult res = null;
@@ -2774,14 +2775,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mWindowManagerInternal.getDisplayIdForWindow(windowToken);
synchronized (mMethodMap) {
if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason="
- + InputMethodClient.getStartInputReason(startInputReason)
+ + InputMethodDebug.startInputReasonToString(startInputReason)
+ " client=" + client.asBinder()
+ " inputContext=" + inputContext
+ " missingMethods="
+ InputConnectionInspector.getMissingMethodFlagsAsString(missingMethods)
+ " attribute=" + attribute
+ " controlFlags=#" + Integer.toHexString(controlFlags)
- + " softInputMode=" + InputMethodClient.softInputModeToString(softInputMode)
+ + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
+ " windowFlags=#" + Integer.toHexString(windowFlags)
+ " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion);
@@ -4579,7 +4580,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
p.println(" mCurClient=" + client + " mCurSeq=" + mCurSeq);
p.println(" mCurFocusedWindow=" + mCurFocusedWindow
+ " softInputMode=" +
- InputMethodClient.softInputModeToString(mCurFocusedWindowSoftInputMode)
+ InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode)
+ " client=" + mCurFocusedWindowClient);
focusedWindowClient = mCurFocusedWindowClient;
p.println(" mCurId=" + mCurId + " mHaveConnection=" + mHaveConnection
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 3f8941dfb21b..4ece538d6d31 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -57,6 +57,8 @@ import java.util.function.Predicate;
* This isn't strictly necessary because each controller is only interested in a specific field,
* and the receivers that are listening for global state change will all run on the main looper,
* but we don't enforce that so this is safer.
+ *
+ * Test: atest com.android.server.job.controllers.JobStatusTest
* @hide
*/
public final class JobStatus {
@@ -154,7 +156,9 @@ public final class JobStatus {
// Constraints.
final int requiredConstraints;
+ private final int mRequiredConstraintsOfInterest;
int satisfiedConstraints = 0;
+ private int mSatisfiedConstraintsOfInterest = 0;
// Set to true if doze constraint was satisfied due to app being whitelisted.
public boolean dozeWhitelisted;
@@ -265,6 +269,28 @@ public final class JobStatus {
private long totalNetworkBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
+ /////// Booleans that track if a job is ready to run. They should be updated whenever dependent
+ /////// states change.
+
+ /**
+ * The deadline for the job has passed. This is only good for non-periodic jobs. A periodic job
+ * should only run if its constraints are satisfied.
+ * Computed as: NOT periodic AND has deadline constraint AND deadline constraint satisfied.
+ */
+ private boolean mReadyDeadlineSatisfied;
+
+ /**
+ * The device isn't Dozing or this job will be in the foreground. This implicit constraint must
+ * be satisfied.
+ */
+ private boolean mReadyNotDozing;
+
+ /**
+ * The job is not restricted from running in the background (due to Battery Saver). This
+ * implicit constraint must be satisfied.
+ */
+ private boolean mReadyNotRestrictedInBg;
+
/** Provide a handle to the service that this job will be run on. */
public int getServiceToken() {
return callingUid;
@@ -349,6 +375,8 @@ public final class JobStatus {
requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
}
this.requiredConstraints = requiredConstraints;
+ mRequiredConstraintsOfInterest = requiredConstraints & CONSTRAINTS_OF_INTEREST;
+ mReadyNotDozing = (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
mLastSuccessfulRunTime = lastSuccessfulRunTime;
mLastFailedRunTime = lastFailedRunTime;
@@ -865,7 +893,12 @@ public final class JobStatus {
}
boolean setDeadlineConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_DEADLINE, state);
+ if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) {
+ // The constraint was changed. Update the ready flag.
+ mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
+ return true;
+ }
+ return false;
}
boolean setIdleConstraintSatisfied(boolean state) {
@@ -882,11 +915,21 @@ public final class JobStatus {
boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
dozeWhitelisted = whitelisted;
- return setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state);
+ if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
+ // The constraint was changed. Update the ready flag.
+ mReadyNotDozing = state || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ return true;
+ }
+ return false;
}
boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state);
+ if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) {
+ // The constraint was changed. Update the ready flag.
+ mReadyNotRestrictedInBg = state;
+ return true;
+ }
+ return false;
}
boolean setUidActive(final boolean newActiveState) {
@@ -903,6 +946,7 @@ public final class JobStatus {
return false;
}
satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
+ mSatisfiedConstraintsOfInterest = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
return true;
}
@@ -933,24 +977,15 @@ public final class JobStatus {
/**
* @return Whether or not this job is ready to run, based on its requirements. This is true if
* the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
- * TODO: This function is called a *lot*. We should probably just have it check an
- * already-computed boolean, which we updated whenever we see one of the states it depends
- * on here change.
*/
public boolean isReady() {
// Deadline constraint trumps other constraints (except for periodic jobs where deadline
// is an implementation detail. A periodic job should only run if its constraints are
// satisfied).
- // AppNotIdle implicit constraint must be satisfied
// DeviceNotDozing implicit constraint must be satisfied
// NotRestrictedInBackground implicit constraint must be satisfied
- final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint()
- && (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0);
- final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0
- || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
- final boolean notRestrictedInBg =
- (satisfiedConstraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0;
- return (isConstraintsSatisfied() || deadlineSatisfied) && notDozing && notRestrictedInBg;
+ return mReadyNotDozing && mReadyNotRestrictedInBg && (mReadyDeadlineSatisfied
+ || isConstraintsSatisfied());
}
static final int CONSTRAINTS_OF_INTEREST = CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
@@ -971,15 +1006,13 @@ public final class JobStatus {
return true;
}
- final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST;
-
- int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+ int sat = mSatisfiedConstraintsOfInterest;
if (overrideState == OVERRIDE_SOFT) {
// override: pretend all 'soft' requirements are satisfied
sat |= (requiredConstraints & SOFT_OVERRIDE_CONSTRAINTS);
}
- return (sat & req) == req;
+ return (sat & mRequiredConstraintsOfInterest) == mRequiredConstraintsOfInterest;
}
public boolean matches(int uid, int jobId) {
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index b29b7cf5a712..99a04d7b144f 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.IContexthub;
import android.hardware.contexthub.V1_0.Result;
+import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubTransaction;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
@@ -57,9 +58,9 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
private final ContextHubClientManager mClientManager;
/*
- * The ID of the hub that this client is attached to.
+ * The object describing the hub that this client is attached to.
*/
- private final int mAttachedContextHubId;
+ private final ContextHubInfo mAttachedContextHubInfo;
/*
* The host end point ID of this client.
@@ -85,11 +86,12 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
/* package */ ContextHubClientBroker(
Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
- int contextHubId, short hostEndPointId, IContextHubClientCallback callback) {
+ ContextHubInfo contextHubInfo, short hostEndPointId,
+ IContextHubClientCallback callback) {
mContext = context;
mContextHubProxy = contextHubProxy;
mClientManager = clientManager;
- mAttachedContextHubId = contextHubId;
+ mAttachedContextHubInfo = contextHubInfo;
mHostEndPointId = hostEndPointId;
mCallbackInterface = callback;
}
@@ -119,11 +121,12 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
ContextHubMsg messageToNanoApp = ContextHubServiceUtil.createHidlContextHubMessage(
mHostEndPointId, message);
+ int contextHubId = mAttachedContextHubInfo.getId();
try {
- result = mContextHubProxy.sendMessageToHub(mAttachedContextHubId, messageToNanoApp);
+ result = mContextHubProxy.sendMessageToHub(contextHubId, messageToNanoApp);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in sendMessageToNanoApp (target hub ID = "
- + mAttachedContextHubId + ")", e);
+ + contextHubId + ")", e);
result = Result.UNKNOWN_FAILURE;
}
} else {
@@ -156,7 +159,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
* @return the ID of the context hub this client is attached to
*/
/* package */ int getAttachedContextHubId() {
- return mAttachedContextHubId;
+ return mAttachedContextHubInfo.getId();
}
/**
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 4243f02a15b2..eda8c6f8b418 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -19,13 +19,13 @@ package com.android.server.location;
import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.IContexthub;
+import android.hardware.location.ContextHubInfo;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
import android.os.RemoteException;
import android.util.Log;
-import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@@ -80,15 +80,15 @@ import java.util.function.Consumer;
* Registers a new client with the service.
*
* @param clientCallback the callback interface of the client to register
- * @param contextHubId the ID of the hub this client is attached to
+ * @param contextHubInfo the object describing the hub this client is attached to
*
* @return the client interface
*
* @throws IllegalStateException if max number of clients have already registered
*/
/* package */ IContextHubClient registerClient(
- IContextHubClientCallback clientCallback, int contextHubId) {
- ContextHubClientBroker broker = createNewClientBroker(clientCallback, contextHubId);
+ IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) {
+ ContextHubClientBroker broker = createNewClientBroker(clientCallback, contextHubInfo);
try {
broker.attachDeathRecipient();
@@ -183,14 +183,14 @@ import java.util.function.Consumer;
* manager.
*
* @param clientCallback the callback interface of the client to register
- * @param contextHubId the ID of the hub this client is attached to
+ * @param contextHubInfo the object describing the hub this client is attached to
*
* @return the ContextHubClientBroker object
*
* @throws IllegalStateException if max number of clients have already registered
*/
private synchronized ContextHubClientBroker createNewClientBroker(
- IContextHubClientCallback clientCallback, int contextHubId) {
+ IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) {
if (mHostEndPointIdToClientMap.size() == MAX_CLIENT_ID + 1) {
throw new IllegalStateException("Could not register client - max limit exceeded");
}
@@ -198,10 +198,11 @@ import java.util.function.Consumer;
ContextHubClientBroker broker = null;
int id = mNextHostEndpointId;
for (int i = 0; i <= MAX_CLIENT_ID; i++) {
- if (!mHostEndPointIdToClientMap.containsKey((short)id)) {
+ if (!mHostEndPointIdToClientMap.containsKey((short) id)) {
broker = new ContextHubClientBroker(
- mContext, mContextHubProxy, this, contextHubId, (short)id, clientCallback);
- mHostEndPointIdToClientMap.put((short)id, broker);
+ mContext, mContextHubProxy, this, contextHubInfo, (short) id,
+ clientCallback);
+ mHostEndPointIdToClientMap.put((short) id, broker);
mNextHostEndpointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
break;
}
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 27509deb958f..96e9337a7932 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -170,8 +170,9 @@ public class ContextHubService extends IContextHubService.Stub {
HashMap<Integer, IContextHubClient> defaultClientMap = new HashMap<>();
for (int contextHubId : mContextHubIdToInfoMap.keySet()) {
+ ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
IContextHubClient client = mClientManager.registerClient(
- createDefaultClientCallback(contextHubId), contextHubId);
+ createDefaultClientCallback(contextHubId), contextHubInfo);
defaultClientMap.put(contextHubId, client);
try {
@@ -623,7 +624,8 @@ public class ContextHubService extends IContextHubService.Stub {
throw new NullPointerException("Cannot register client with null callback");
}
- return mClientManager.registerClient(clientCallback, contextHubId);
+ ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
+ return mClientManager.registerClient(clientCallback, contextHubInfo);
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 506cc441c868..93b83ae72cca 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -719,8 +719,7 @@ public class NotificationManagerService extends SystemService {
return;
}
final long now = System.currentTimeMillis();
- MetricsLogger.action(r.getLogMaker(now)
- .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+ MetricsLogger.action(r.getItemLogMaker()
.setType(MetricsEvent.TYPE_ACTION)
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_COUNT, nv.count));
@@ -865,8 +864,7 @@ public class NotificationManagerService extends SystemService {
r.stats.onExpansionChanged(userAction, expanded);
final long now = System.currentTimeMillis();
if (userAction) {
- MetricsLogger.action(r.getLogMaker(now)
- .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+ MetricsLogger.action(r.getItemLogMaker()
.setType(expanded ? MetricsEvent.TYPE_DETAIL
: MetricsEvent.TYPE_COLLAPSE));
}
@@ -3624,7 +3622,7 @@ public class NotificationManagerService extends SystemService {
INotificationListener token, String pkg, UserHandle user,
NotificationChannelGroup group) throws RemoteException {
Preconditions.checkNotNull(user);
- verifyPrivilegedListener(token, user);
+ verifyPrivilegedListener(token, user, false);
createNotificationChannelGroup(
pkg, getUidForPackageAndUser(pkg, user), group, false, true);
savePolicyFile();
@@ -3637,7 +3635,7 @@ public class NotificationManagerService extends SystemService {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(user);
- verifyPrivilegedListener(token, user);
+ verifyPrivilegedListener(token, user, false);
updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
}
@@ -3646,7 +3644,7 @@ public class NotificationManagerService extends SystemService {
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(user);
- verifyPrivilegedListener(token, user);
+ verifyPrivilegedListener(token, user, true);
return mPreferencesHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
false /* includeDeleted */);
@@ -3658,7 +3656,7 @@ public class NotificationManagerService extends SystemService {
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(user);
- verifyPrivilegedListener(token, user);
+ verifyPrivilegedListener(token, user, true);
List<NotificationChannelGroup> groups = new ArrayList<>();
groups.addAll(mPreferencesHelper.getNotificationChannelGroups(
@@ -3666,13 +3664,18 @@ public class NotificationManagerService extends SystemService {
return new ParceledListSlice<>(groups);
}
- private void verifyPrivilegedListener(INotificationListener token, UserHandle user) {
+ private void verifyPrivilegedListener(INotificationListener token, UserHandle user,
+ boolean assistantAllowed) {
ManagedServiceInfo info;
synchronized (mNotificationLock) {
info = mListeners.checkServiceTokenLocked(token);
}
if (!hasCompanionDevice(info)) {
- throw new SecurityException(info + " does not have access");
+ synchronized (mNotificationLock) {
+ if (!assistantAllowed || !mAssistants.isServiceTokenValidLocked(info.service)) {
+ throw new SecurityException(info + " does not have access");
+ }
+ }
}
if (!info.enabledAndUserMatches(user.getIdentifier())) {
throw new SecurityException(info + " does not have access");
@@ -5842,8 +5845,7 @@ public class NotificationManagerService extends SystemService {
mArchive.record(r.sbn);
final long now = System.currentTimeMillis();
- final LogMaker logMaker = r.getLogMaker(now)
- .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+ final LogMaker logMaker = r.getItemLogMaker()
.setType(MetricsEvent.TYPE_DISMISS)
.setSubtype(reason);
if (rank != -1 && count != -1) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 65ec5808a0dd..e9f2718fe2b3 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -611,6 +611,7 @@ public final class NotificationRecord {
}
public void applyAdjustments() {
+ long now = System.currentTimeMillis();
synchronized (mAdjustments) {
for (Adjustment adjustment: mAdjustments) {
Bundle signals = adjustment.getSignals();
@@ -618,17 +619,25 @@ public final class NotificationRecord {
final ArrayList<String> people =
adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
setPeopleOverride(people);
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_PEOPLE, people.size()));
}
if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) {
final ArrayList<SnoozeCriterion> snoozeCriterionList =
adjustment.getSignals().getParcelableArrayList(
Adjustment.KEY_SNOOZE_CRITERIA);
setSnoozeCriteria(snoozeCriterionList);
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SNOOZE_CRITERIA,
+ snoozeCriterionList.size()));
}
if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) {
final String groupOverrideKey =
adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY);
setOverrideGroupKey(groupOverrideKey);
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_GROUP_KEY,
+ groupOverrideKey));
}
if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) {
// Only allow user sentiment update from assistant if user hasn't already
@@ -637,19 +646,31 @@ public final class NotificationRecord {
&& (getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) {
setUserSentiment(adjustment.getSignals().getInt(
Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_USER_SENTIMENT,
+ getUserSentiment()));
}
}
if (signals.containsKey(Adjustment.KEY_SMART_ACTIONS)) {
setSmartActions(signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_ACTIONS,
+ getSmartActions().size()));
}
if (signals.containsKey(Adjustment.KEY_SMART_REPLIES)) {
setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES));
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_REPLIES,
+ getSmartReplies().size()));
}
if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
importance = Math.min(IMPORTANCE_HIGH, importance);
setAssistantImportance(importance);
+ MetricsLogger.action(getAdjustmentLogMaker()
+ .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_IMPORTANCE,
+ importance));
}
}
}
@@ -732,10 +753,10 @@ public final class NotificationRecord {
protected void calculateImportance() {
mImportance = calculateInitialImportance();
mImportanceExplanation = "app";
- if (getChannel().isImportanceLocked()) {
+ if (getChannel().hasUserSetImportance()) {
mImportanceExplanation = "user";
}
- if (!getChannel().isImportanceLocked() && mAssistantImportance != IMPORTANCE_UNSPECIFIED) {
+ if (!getChannel().hasUserSetImportance() && mAssistantImportance != IMPORTANCE_UNSPECIFIED) {
mImportance = mAssistantImportance;
mImportanceExplanation = "asst";
}
@@ -1203,6 +1224,16 @@ public final class NotificationRecord {
return getLogMaker(System.currentTimeMillis());
}
+ public LogMaker getItemLogMaker() {
+ return getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM);
+ }
+
+ public LogMaker getAdjustmentLogMaker() {
+ return getLogMaker()
+ .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+ .setType(MetricsEvent.NOTIFICATION_ASSISTANT_ADJUSTMENT);
+ }
+
@VisibleForTesting
static final class Light {
public final int color;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 760f1559c845..44b80c138346 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1212,27 +1212,89 @@ public class ZenModeHelper {
}
private final class Metrics extends Callback {
- private static final String COUNTER_PREFIX = "dnd_mode_";
+ private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
+ private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
+ private static final int DND_OFF = 0;
+ private static final int DND_ON_MANUAL = 1;
+ private static final int DND_ON_AUTOMATIC = 2;
+ private static final String COUNTER_RULE = "dnd_rule_count";
private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
+ // Total silence, alarms only, priority only
private int mPreviousZenMode = -1;
- private long mBeginningMs = 0L;
+ private long mModeLogTimeMs = 0L;
+
+ private int mNumZenRules = -1;
+ private long mRuleCountLogTime = 0L;
+
+ // automatic (1) vs manual (0) vs dnd off (2)
+ private int mPreviousZenType = -1;
+ private long mTypeLogTimeMs = 0L;
@Override
void onZenModeChanged() {
emit();
}
+ @Override
+ void onConfigChanged() {
+ emit();
+ }
+
private void emit() {
mHandler.postMetricsTimer();
+ emitZenMode();
+ emitRules();
+ emitDndType();
+ }
+
+ private void emitZenMode() {
final long now = SystemClock.elapsedRealtime();
- final long since = (now - mBeginningMs);
+ final long since = (now - mModeLogTimeMs);
if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
if (mPreviousZenMode != -1) {
- MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since);
+ MetricsLogger.count(
+ mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
}
mPreviousZenMode = mZenMode;
- mBeginningMs = now;
+ mModeLogTimeMs = now;
+ }
+ }
+
+ private void emitRules() {
+ final long now = SystemClock.elapsedRealtime();
+ final long since = (now - mRuleCountLogTime);
+ synchronized (mConfig) {
+ int numZenRules = mConfig.automaticRules.size();
+ if (mNumZenRules != numZenRules
+ || since > MINIMUM_LOG_PERIOD_MS) {
+ if (mNumZenRules != -1) {
+ MetricsLogger.count(mContext, COUNTER_RULE,
+ numZenRules - mNumZenRules);
+ }
+ mNumZenRules = numZenRules;
+
+ mRuleCountLogTime = since;
+ }
+ }
+ }
+
+ private void emitDndType() {
+ final long now = SystemClock.elapsedRealtime();
+ final long since = (now - mTypeLogTimeMs);
+ synchronized (mConfig) {
+ boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
+ int zenType = !dndOn ? DND_OFF
+ : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
+ if (zenType != mPreviousZenType
+ || since > MINIMUM_LOG_PERIOD_MS) {
+ if (mPreviousZenType != -1) {
+ MetricsLogger.count(
+ mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
+ }
+ mTypeLogTimeMs = now;
+ mPreviousZenType = zenType;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index be24c7125969..5569822300b9 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -243,7 +243,7 @@ public class BatterySaverController implements BatterySaverPolicyListener {
}
/**
- * Called by {@link PowerManagerService} to update the battery saver stete.
+ * Called by {@link PowerManagerService} to update the battery saver state.
*/
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
@@ -290,8 +290,8 @@ public class BatterySaverController implements BatterySaverPolicyListener {
* This method is called only in the following cases:
* - When battery saver becomes activated.
* - When battery saver becomes deactivated.
- * - When battery saver is on the interactive state changes.
- * - When battery saver is on the battery saver policy changes.
+ * - When battery saver is on and the interactive state changes.
+ * - When battery saver is on and the battery saver policy changes.
*/
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
final LowPowerModeListener[] listeners;
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 6db7e4f1a800..93870e73ecab 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -88,7 +88,6 @@ import com.android.internal.os.KernelWakelockReader;
import com.android.internal.os.KernelWakelockStats;
import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
-import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
@@ -175,6 +174,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
private IWifiManager mWifiManager = null;
private TelephonyManager mTelephony = null;
+ private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
+ private final StatFs mStatFsSystem =
+ new StatFs(Environment.getRootDirectory().getAbsolutePath());
+ private final StatFs mStatFsTemp =
+ new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@GuardedBy("sStatsdLock")
private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
@GuardedBy("sStatsdLock")
@@ -195,8 +199,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static IThermalService sThermalService;
private File mBaseDir =
new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
- @GuardedBy("this")
- ProcessCpuTracker mProcessCpuTracker = null;
public StatsCompanionService(Context context) {
super();
@@ -770,7 +772,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullBluetoothBytesTransfer(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = fetchBluetoothData();
+ BluetoothActivityEnergyInfo info = pullBluetoothData();
if (info.getUidTraffic() != null) {
for (UidTraffic traffic : info.getUidTraffic()) {
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
@@ -882,12 +884,9 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- synchronized (this) {
- if (mWifiManager == null) {
- mWifiManager =
- IWifiManager.Stub.asInterface(
- ServiceManager.getService(Context.WIFI_SERVICE));
- }
+ if (mWifiManager == null) {
+ mWifiManager =
+ IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
}
if (mWifiManager != null) {
try {
@@ -917,10 +916,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- synchronized (this) {
- if (mTelephony == null) {
- mTelephony = TelephonyManager.from(mContext);
- }
+ if (mTelephony == null) {
+ mTelephony = TelephonyManager.from(mContext);
}
if (mTelephony != null) {
SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -944,7 +941,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullBluetoothActivityInfo(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = fetchBluetoothData();
+ BluetoothActivityEnergyInfo info = pullBluetoothData();
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
e.writeLong(info.getTimeStamp());
e.writeInt(info.getBluetoothStackState());
@@ -955,7 +952,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pulledData.add(e);
}
- private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
+ private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
@@ -1326,35 +1323,30 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullProcessStats(int section, int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- synchronized (this) {
- try {
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
- List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
- long highWaterMark = mProcessStats.getCommittedStats(
- lastHighWaterMark, section, true, statsFiles);
- if (statsFiles.size() != 1) {
- return;
- }
- InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
- statsFiles.get(0));
- int[] len = new int[1];
- byte[] stats = readFully(stream, len);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- e.writeStorage(Arrays.copyOf(stats, len[0]));
- pulledData.add(e);
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
- + lastHighWaterMark).delete();
- new File(
- mBaseDir.getAbsolutePath() + "/" + section + "_"
- + highWaterMark).createNewFile();
- } catch (IOException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
+ try {
+ long lastHighWaterMark = readProcStatsHighWaterMark(section);
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ long highWaterMark = mProcessStats.getCommittedStats(
+ lastHighWaterMark, section, true, statsFiles);
+ if (statsFiles.size() != 1) {
+ return;
}
+ InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
+ int[] len = new int[1];
+ byte[] stats = readFully(stream, len);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeStorage(Arrays.copyOf(stats, len[0]));
+ pulledData.add(e);
+ new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark).delete();
+ new File(
+ mBaseDir.getAbsolutePath() + "/" + section + "_"
+ + highWaterMark).createNewFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
}
}
@@ -1423,34 +1415,12 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
});
}
- private void pullProcessCpuTime(int tagId, long elapsedNanos, final long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- synchronized (this) {
- if (mProcessCpuTracker == null) {
- mProcessCpuTracker = new ProcessCpuTracker(false);
- mProcessCpuTracker.init();
- }
- mProcessCpuTracker.update();
- for (int i = 0; i < mProcessCpuTracker.countStats(); i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- e.writeInt(st.uid);
- e.writeString(st.name);
- e.writeLong(st.base_utime);
- e.writeLong(st.base_stime);
- pulledData.add(e);
- }
- }
- }
-
/**
* Pulls various data.
*/
@Override // Binder call
public StatsLogEventWrapper[] pullData(int tagId) {
enforceCallingPermission();
-
if (DEBUG) {
Slog.d(TAG, "Pulling " + tagId);
}
@@ -1563,8 +1533,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
break;
}
case StatsLog.PROC_STATS: {
- pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos,
- ret);
+ pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos, ret);
break;
}
case StatsLog.PROC_STATS_PKG_PROC: {
@@ -1580,10 +1549,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullPowerProfile(tagId, elapsedNanos, wallClockNanos, ret);
break;
}
- case StatsLog.PROCESS_CPU_TIME: {
- pullProcessCpuTime(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 26ea152761fb..b88165ef0f24 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -206,6 +206,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsLog;
import android.util.Xml;
import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
@@ -9387,6 +9388,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
saveUserRestrictionsLocked(userHandle);
}
+ StatsLog.write(StatsLog.USER_RESTRICTION_CHANGED, key, enabledFromThisOwner);
if (SecurityLog.isLoggingEnabled()) {
final int eventTag = enabledFromThisOwner
? SecurityLog.TAG_USER_RESTRICTION_ADDED
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 1752479ade35..b63138edfd21 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -16,19 +16,27 @@
package com.android.server.job.controllers;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
import static org.junit.Assert.assertEquals;
import android.app.job.JobInfo;
import android.content.ComponentName;
+import android.content.pm.PackageManagerInternal;
import android.os.SystemClock;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
import java.time.Clock;
import java.time.ZoneOffset;
@@ -37,8 +45,17 @@ import java.time.ZoneOffset;
public class JobStatusTest {
private static final double DELTA = 0.00001;
+ private MockitoSession mMockingSession;
+
@Before
public void setUp() throws Exception {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(LocalServices.class)
+ .startMocking();
+ doReturn(mock(PackageManagerInternal.class))
+ .when(() -> LocalServices.getService(PackageManagerInternal.class));
+
// Freeze the clocks at this moment in time
JobSchedulerService.sSystemClock =
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
@@ -48,6 +65,13 @@ public class JobStatusTest {
Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
}
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
@Test
public void testFraction() throws Exception {
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
index ea90ffd0792f..0da574239666 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
@@ -20,11 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
import android.platform.test.annotations.Presubmit;
@@ -131,4 +134,57 @@ public class ActivityDisplayTests extends ActivityTestsBase {
new ActivityBuilder(mService).setTask(fullscreenTask).build();
return fullscreenStack;
}
+
+ /**
+ * Verifies the correct activity is returned when querying the top running activity.
+ */
+ @Test
+ public void testTopRunningActivity() {
+ // Create stack to hold focus.
+ final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+ final KeyguardController keyguard = mSupervisor.getKeyguardController();
+ final ActivityStack stack = mSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(stack).build();
+
+ // Make sure the top running activity is not affected when keyguard is not locked.
+ assertTopRunningActivity(activity, display);
+
+ // Check to make sure activity not reported when it cannot show on lock and lock is on.
+ doReturn(true).when(keyguard).isKeyguardLocked();
+ assertEquals(activity, display.topRunningActivity());
+ assertNull(display.topRunningActivity(true /* considerKeyguardState */));
+
+ // Change focus to stack with activity.
+ stack.moveToFront("focusChangeToTestStack");
+ assertEquals(stack, display.getFocusedStack());
+ assertEquals(activity, display.topRunningActivity());
+ assertNull(display.topRunningActivity(true /* considerKeyguardState */));
+
+ // Add activity that should be shown on the keyguard.
+ final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(stack)
+ .setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
+ .build();
+
+ // Ensure the show when locked activity is returned.
+ assertTopRunningActivity(showWhenLockedActivity, display);
+
+ // Change focus back to empty stack.
+ emptyStack.moveToFront("focusChangeToEmptyStack");
+ assertEquals(emptyStack, display.getFocusedStack());
+ // If there is no running activity in focused stack, the running activity in next focusable
+ // stack should be returned.
+ assertTopRunningActivity(showWhenLockedActivity, display);
+ }
+
+ private static void assertTopRunningActivity(ActivityRecord top, ActivityDisplay display) {
+ assertEquals(top, display.topRunningActivity());
+ assertEquals(top, display.topRunningActivity(true /* considerKeyguardState */));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index c44e492e308b..f42f5b1fff2e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -64,6 +64,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -102,6 +103,7 @@ import java.util.function.Function;
* com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
*/
@SmallTest
+@FlakyTest(bugId = 113616538)
@RunWith(AndroidJUnit4.class)
public class ActivityManagerServiceTest {
private static final String TAG = ActivityManagerServiceTest.class.getSimpleName();
@@ -173,7 +175,7 @@ public class ActivityManagerServiceTest {
true); // expectNotify
// Explicitly setting the seq counter for more verification.
- mAms.mProcStateSeqCounter = 42;
+ mAms.mProcessList.mProcStateSeqCounter = 42;
// Uid state is not moving from background to foreground or vice versa.
verifySeqCounterAndInteractions(uidRec,
@@ -260,7 +262,7 @@ public class ActivityManagerServiceTest {
final ProcessRecord appRec = new ProcessRecord(mAms, new ApplicationInfo(), TAG, uid, null);
appRec.thread = Mockito.mock(IApplicationThread.class);
- mAms.mLruProcesses.add(appRec);
+ mAms.mProcessList.mLruProcesses.add(appRec);
return uidRec;
}
@@ -275,11 +277,11 @@ public class ActivityManagerServiceTest {
uidRec.curProcState = curState;
mAms.incrementProcStateSeqAndNotifyAppsLocked();
- assertEquals(expectedGlobalCounter, mAms.mProcStateSeqCounter);
+ assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
assertEquals(expectedCurProcStateSeq, uidRec.curProcStateSeq);
- for (int i = mAms.mLruProcesses.size() - 1; i >= 0; --i) {
- final ProcessRecord app = mAms.mLruProcesses.get(i);
+ for (int i = mAms.mProcessList.getLruSizeLocked() - 1; i >= 0; --i) {
+ final ProcessRecord app = mAms.mProcessList.mLruProcesses.get(i);
// AMS should notify apps only for block states other than NETWORK_STATE_NO_CHANGE.
if (app.uid == uidRec.uid && expectedBlockState == NETWORK_STATE_BLOCK) {
verify(app.thread).setNetworkBlockSeq(uidRec.curProcStateSeq);
@@ -829,4 +831,4 @@ public class ActivityManagerServiceTest {
mRestricted = restricted;
}
}
-} \ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index cc7a24d5700e..2c993d32c20c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -25,7 +25,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -307,62 +306,6 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
}
/**
- * Verifies the correct activity is returned when querying the top running activity.
- */
- @Test
- public void testTopRunningActivity() throws Exception {
- // Create stack to hold focus
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD, true /* onTop */);
-
- final KeyguardController keyguard = mSupervisor.getKeyguardController();
- final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(stack).build();
-
- // Make sure the top running activity is not affected when keyguard is not locked
- assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
- assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */));
-
- // Check to make sure activity not reported when it cannot show on lock and lock is on.
- doReturn(true).when(keyguard).isKeyguardLocked();
- assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
- assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */));
-
- // Change focus to stack with activity.
- stack.moveToFront("focusChangeToTestStack");
- assertEquals(stack, display.getFocusedStack());
- assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
- assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */));
-
- // Add activity that should be shown on the keyguard.
- final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService)
- .setCreateTask(true)
- .setStack(stack)
- .setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
- .build();
-
- // Ensure the show when locked activity is returned.
- assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked());
- assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */));
-
- // Change focus back to empty stack
- emptyStack.moveToFront("focusChangeToEmptyStack");
- assertEquals(emptyStack, display.getFocusedStack());
- // Looking for running activity only in top and focused stack, so nothing should be returned
- // from empty stack.
- assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked());
- assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
- true /* considerKeyguardState */));
- }
-
- /**
* Verify that split-screen primary stack will be chosen if activity is launched that targets
* split-screen secondary, but a matching existing instance is found on top of split-screen
* primary stack.
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 5fcd2aa35e05..53f67afb629e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -26,6 +26,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
@@ -35,10 +38,14 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyInt;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.content.pm.ActivityInfo;
import android.os.UserHandle;
@@ -655,6 +662,39 @@ public class ActivityStackTests extends ActivityTestsBase {
}
@Test
+ public void testFinishCurrentActivity() {
+ // Create 2 activities on a new display.
+ final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+ final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityStack stack2 = createStackForShouldBeVisibleTest(display,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+ // There is still an activity1 in stack1 so the activity2 should be added to finishing list
+ // that will be destroyed until idle.
+ final ActivityRecord activity2 = finishCurrentActivity(stack2);
+ assertEquals(FINISHING, activity2.getState());
+ assertTrue(mSupervisor.mFinishingActivities.contains(activity2));
+
+ // The display becomes empty. Since there is no next activity to be idle, the activity
+ // should be destroyed immediately with updating configuration to restore original state.
+ final ActivityRecord activity1 = finishCurrentActivity(stack1);
+ assertEquals(DESTROYING, activity1.getState());
+ verify(mSupervisor).ensureVisibilityAndConfig(eq(null) /* starting */,
+ eq(display.mDisplayId), anyBoolean(), anyBoolean());
+ }
+
+ private ActivityRecord finishCurrentActivity(ActivityStack stack) {
+ final ActivityRecord activity = stack.topRunningActivityLocked();
+ assertNotNull(activity);
+ activity.setState(PAUSED, "finishCurrentActivity");
+ activity.makeFinishingLocked();
+ stack.finishCurrentActivityLocked(activity, ActivityStack.FINISH_AFTER_VISIBLE,
+ false /* oomAdj */, "finishCurrentActivity");
+ return activity;
+ }
+
+ @Test
public void testShouldSleepActivities() throws Exception {
// When focused activity and keyguard is going away, we should not sleep regardless
// of the display state
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 58fe70d7d992..01d51e44146c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -58,8 +58,9 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.HandlerThread;
+import android.os.Handler;
import android.os.Looper;
+import android.os.Process;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.testing.DexmakerShareClassLoaderRule;
@@ -69,7 +70,9 @@ import android.view.DisplayInfo;
import androidx.test.InstrumentationRegistry;
import com.android.internal.app.IVoiceInteractor;
+import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
+import com.android.server.ServiceThread;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.RootWindowContainerController;
@@ -82,6 +85,7 @@ import org.junit.After;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
+import java.io.File;
import java.util.List;
/**
@@ -97,7 +101,7 @@ public class ActivityTestsBase {
new DexmakerShareClassLoaderRule();
private final Context mContext = InstrumentationRegistry.getContext();
- private HandlerThread mHandlerThread;
+ final TestInjector mTestInjector = new TestInjector();
ActivityTaskManagerService mService;
ActivityStackSupervisor mSupervisor;
@@ -115,13 +119,12 @@ public class ActivityTestsBase {
MockitoAnnotations.initMocks(this);
AttributeCache.init(mContext);
}
- mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
- mHandlerThread.start();
+ mTestInjector.setUp();
}
@After
public void tearDown() {
- mHandlerThread.quitSafely();
+ mTestInjector.tearDown();
}
protected ActivityTaskManagerService createActivityTaskManagerService() {
@@ -143,7 +146,7 @@ public class ActivityTestsBase {
}
ActivityManagerService setupActivityManagerService(TestActivityTaskManagerService atm) {
- final TestActivityManagerService am = spy(new TestActivityManagerService(mContext, atm));
+ final TestActivityManagerService am = spy(new TestActivityManagerService(mTestInjector));
setupActivityManagerService(am, atm);
return am;
}
@@ -173,6 +176,7 @@ public class ActivityTestsBase {
doReturn(mockPackageManager).when(am).getPackageManagerInternalLocked();
doReturn(null).when(mockPackageManager).getDefaultHomeActivity(anyInt());
doNothing().when(am).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
+ am.mActivityTaskManager = atm;
am.mWindowManager = prepareMockWindowManager();
atm.setWindowManager(am.mWindowManager);
@@ -192,8 +196,6 @@ public class ActivityTestsBase {
// An id appended to the end of the component name to make it unique
private static int sCurrentActivityId = 0;
-
-
private final ActivityTaskManagerService mService;
private ComponentName mComponent;
@@ -487,6 +489,40 @@ public class ActivityTestsBase {
}
}
+ private static class TestInjector extends ActivityManagerService.Injector {
+ private ServiceThread mHandlerThread;
+
+ @Override
+ public Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ @Override
+ public AppOpsService getAppOpsService(File file, Handler handler) {
+ return null;
+ }
+
+ @Override
+ public Handler getUiHandler(ActivityManagerService service) {
+ return mHandlerThread.getThreadHandler();
+ }
+
+ @Override
+ public boolean isNetworkRestrictedForUid(int uid) {
+ return false;
+ }
+
+ void setUp() {
+ mHandlerThread = new ServiceThread("ActivityTestsThread",
+ Process.THREAD_PRIORITY_DEFAULT, true /* allowIo */);
+ mHandlerThread.start();
+ }
+
+ void tearDown() {
+ mHandlerThread.quitSafely();
+ }
+ }
+
/**
* An {@link ActivityManagerService} subclass which provides a test
* {@link ActivityStackSupervisor}.
@@ -495,8 +531,8 @@ public class ActivityTestsBase {
private ActivityManagerInternal mInternal;
- TestActivityManagerService(Context context, TestActivityTaskManagerService atm) {
- super(context, atm);
+ TestActivityManagerService(TestInjector testInjector) {
+ super(testInjector, testInjector.mHandlerThread);
mUgmInternal = mock(UriGrantsManagerInternal.class);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
index 3819e2190d88..06d41f1919c8 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -21,6 +21,7 @@ import android.os.Handler;
import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -37,6 +38,7 @@ import java.io.File;
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
+@FlakyTest(bugId = 113616538)
public class AppErrorDialogTest {
private Context mContext;
diff --git a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
index a030210398d6..1b823ff8c6b4 100644
--- a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
@@ -46,6 +46,7 @@ import android.util.Log;
import android.view.IWindowManager;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
@@ -67,6 +68,7 @@ import java.util.concurrent.TimeUnit;
* runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
*/
@MediumTest
+@FlakyTest(bugId = 113616538)
@RunWith(AndroidJUnit4.class)
public class AssistDataRequesterTest extends ActivityTestsBase {
diff --git a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
index 62c5734561f9..75f7c4c2cdff 100644
--- a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -45,7 +45,7 @@ import java.util.List;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
-public class BroadcastRecordTest extends ActivityTestsBase {
+public class BroadcastRecordTest {
@Test
public void testCleanupDisabledPackageReceivers() {
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 1276f656f914..27e8c632c1bd 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -116,8 +116,7 @@ public class RecentTasksTest extends ActivityTestsBase {
mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
mService = spy(new MyTestActivityTaskManagerService(mContext));
- final TestActivityManagerService am =
- spy(new MyTestActivityManagerService(mContext, mService));
+ final TestActivityManagerService am = spy(new MyTestActivityManagerService());
setupActivityManagerService(am, mService);
mRecentTasks = (TestRecentTasks) mService.getRecentTasks();
mRecentTasks.loadParametersFromResources(mContext.getResources());
@@ -848,8 +847,8 @@ public class RecentTasksTest extends ActivityTestsBase {
}
private class MyTestActivityManagerService extends TestActivityManagerService {
- MyTestActivityManagerService(Context context, TestActivityTaskManagerService atm) {
- super(context, atm);
+ MyTestActivityManagerService() {
+ super(mTestInjector);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
index 921cdea2e646..27766d3d8d6c 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
@@ -69,13 +69,11 @@ public class TaskRecordTests extends ActivityTestsBase {
private static final String TASK_TAG = "task";
- private ActivityTaskManagerService mService;
-
@Before
public void setUp() throws Exception {
super.setUp();
TaskRecord.setTaskRecordFactory(null);
- mService = createActivityTaskManagerService();
+ setupActivityTaskManagerService();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 869f8fa0c2fa..caaa0bbe6c60 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -43,6 +43,7 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
@@ -92,6 +93,8 @@ public class AppStandbyControllerTests {
private static final int USER_ID = 0;
private static final int USER_ID2 = 10;
+ private static final String PACKAGE_UNKNOWN = "com.example.unknown";
+
private static final String ADMIN_PKG = "com.android.admin";
private static final String ADMIN_PKG2 = "com.android.admin2";
private static final String ADMIN_PKG3 = "com.android.admin3";
@@ -106,6 +109,9 @@ public class AppStandbyControllerTests {
// Short STABLE_CHARGING_THRESHOLD for testing purposes
private static final long STABLE_CHARGING_THRESHOLD = 2000;
+ /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
+ private static boolean isPackageInstalled = true;
+
private MyInjector mInjector;
private AppStandbyController mController;
@@ -183,6 +189,12 @@ public class AppStandbyControllerTests {
}
@Override
+ boolean isPackageInstalled(String packageName, int flags, int userId) {
+ // Should always return true (default value) unless testing for an uninstalled app
+ return isPackageInstalled;
+ }
+
+ @Override
int[] getRunningUserIds() {
return new int[] {USER_ID};
}
@@ -403,30 +415,30 @@ public class AppStandbyControllerTests {
false));
}
- private void reportEvent(AppStandbyController controller, int eventType,
- long elapsedTime) {
+ private void reportEvent(AppStandbyController controller, int eventType, long elapsedTime,
+ String packageName) {
// Back to ACTIVE on event
mInjector.mElapsedRealtime = elapsedTime;
UsageEvents.Event ev = new UsageEvents.Event();
- ev.mPackage = PACKAGE_1;
+ ev.mPackage = packageName;
ev.mEventType = eventType;
controller.reportEvent(ev, elapsedTime, USER_ID);
}
- private int getStandbyBucket(AppStandbyController controller) {
- return controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
+ private int getStandbyBucket(AppStandbyController controller, String packageName) {
+ return controller.getAppStandbyBucket(packageName, USER_ID, mInjector.mElapsedRealtime,
true);
}
private void assertBucket(int bucket) {
- assertEquals(bucket, getStandbyBucket(mController));
+ assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
}
@Test
public void testBuckets() throws Exception {
assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
// ACTIVE bucket
assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
@@ -443,7 +455,7 @@ public class AppStandbyControllerTests {
// RARE bucket
assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE);
- reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1);
+ reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1, PACKAGE_1);
assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE);
@@ -452,12 +464,48 @@ public class AppStandbyControllerTests {
}
@Test
+ public void testSetAppStandbyBucket() throws Exception {
+ // For a known package, standby bucket should be set properly
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_MAIN_TIMEOUT, HOUR_MS);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
+
+ // For an unknown package, standby bucket should not be set, hence NEVER is returned
+ // Ensure the unknown package is not already in history by removing it
+ mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
+ isPackageInstalled = false; // Mock package is not installed
+ mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_MAIN_TIMEOUT, HOUR_MS);
+ isPackageInstalled = true; // Reset mocked variable for other tests
+ assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
+ }
+
+ @Test
+ public void testAppStandbyBucketOnInstallAndUninstall() throws Exception {
+ // On package install, standby bucket should be ACTIVE
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_UNKNOWN);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_UNKNOWN));
+
+ // On uninstall, package should not exist in history and should return a NEVER bucket
+ mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
+ assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
+ // Ensure uninstalled app is not in history
+ List<AppStandbyInfo> buckets = mController.getAppStandbyBuckets(USER_ID);
+ for(AppStandbyInfo bucket : buckets) {
+ if (bucket.mPackageName.equals(PACKAGE_UNKNOWN)) {
+ fail("packageName found in app idle history after uninstall.");
+ }
+ }
+ }
+
+ @Test
public void testScreenTimeAndBuckets() throws Exception {
mInjector.setDisplayOn(false);
assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
// ACTIVE bucket
assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
@@ -468,7 +516,7 @@ public class AppStandbyControllerTests {
// RARE bucket, should fail because the screen wasn't ON.
mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
mController.checkIdleStates(USER_ID);
- assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
+ assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
mInjector.setDisplayOn(true);
assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
@@ -477,7 +525,7 @@ public class AppStandbyControllerTests {
@Test
public void testForcedIdle() throws Exception {
mController.forceIdleState(PACKAGE_1, USER_ID, true);
- assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
mController.forceIdleState(PACKAGE_1, USER_ID, false);
@@ -488,35 +536,35 @@ public class AppStandbyControllerTests {
@Test
public void testNotificationEvent() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
mInjector.mElapsedRealtime = 1;
- reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
mController.forceIdleState(PACKAGE_1, USER_ID, true);
- reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
- assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
+ reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
}
@Test
public void testSlicePinnedEvent() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
mInjector.mElapsedRealtime = 1;
- reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
mController.forceIdleState(PACKAGE_1, USER_ID, true);
- reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime);
- assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
+ reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
}
@Test
public void testSlicePinnedPrivEvent() throws Exception {
mController.forceIdleState(PACKAGE_1, USER_ID, true);
- reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime, PACKAGE_1);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
}
@Test
@@ -524,28 +572,28 @@ public class AppStandbyControllerTests {
// Set it to timeout or usage, so that prediction can override it
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
REASON_MAIN_TIMEOUT, HOUR_MS);
- assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
REASON_MAIN_PREDICTED, HOUR_MS);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
// Fast forward 12 hours
mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
mController.checkIdleStates(USER_ID);
// Should still be in predicted bucket, since prediction timeout is 1 day since prediction
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
// Fast forward two more hours
mInjector.mElapsedRealtime += 2 * HOUR_MS;
mController.checkIdleStates(USER_ID);
// Should have now applied prediction timeout
- assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
// Fast forward RARE bucket
mInjector.mElapsedRealtime += RARE_THRESHOLD;
mController.checkIdleStates(USER_ID);
// Should continue to apply prediction timeout
- assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
}
@Test
@@ -553,33 +601,33 @@ public class AppStandbyControllerTests {
// Can force to NEVER
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
REASON_MAIN_FORCED, 1 * HOUR_MS);
- assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't override FORCED reason
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
REASON_MAIN_FORCED, 1 * HOUR_MS);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
REASON_MAIN_PREDICTED, 1 * HOUR_MS);
- assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't override NEVER
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
REASON_MAIN_DEFAULT, 2 * HOUR_MS);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
REASON_MAIN_PREDICTED, 2 * HOUR_MS);
- assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't set to NEVER
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
REASON_MAIN_USAGE, 2 * HOUR_MS);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
REASON_MAIN_PREDICTED, 2 * HOUR_MS);
- assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
}
@Test
public void testTimeout() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
mInjector.mElapsedRealtime = 2000;
@@ -601,10 +649,10 @@ public class AppStandbyControllerTests {
@Test
public void testCascadingTimeouts() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
- reportEvent(mController, NOTIFICATION_SEEN, 1000);
+ reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
@@ -622,14 +670,15 @@ public class AppStandbyControllerTests {
@Test
public void testOverlappingTimeouts() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
- reportEvent(mController, NOTIFICATION_SEEN, 1000);
+ reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Overlapping USER_INTERACTION before previous one times out
- reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000);
+ reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000,
+ PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Still in ACTIVE after first USER_INTERACTION times out
@@ -654,14 +703,14 @@ public class AppStandbyControllerTests {
public void testSystemInteractionTimeout() throws Exception {
setChargingState(mController, false);
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
// Fast forward to RARE
mInjector.mElapsedRealtime = RARE_THRESHOLD + 100;
mController.checkIdleStates(USER_ID);
assertBucket(STANDBY_BUCKET_RARE);
// Trigger a SYSTEM_INTERACTION and verify bucket
- reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime);
+ reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Verify it's still in ACTIVE close to end of timeout
@@ -677,11 +726,11 @@ public class AppStandbyControllerTests {
@Test
public void testPredictionNotOverridden() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
- reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
+ reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Falls back to WORKING_SET
@@ -703,7 +752,7 @@ public class AppStandbyControllerTests {
@Test
public void testPredictionStrikesBack() throws Exception {
- reportEvent(mController, USER_INTERACTION, 0);
+ reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Predict to FREQUENT
@@ -714,7 +763,7 @@ public class AppStandbyControllerTests {
// Add a short timeout event
mInjector.mElapsedRealtime += 1000;
- reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime);
+ reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
assertBucket(STANDBY_BUCKET_ACTIVE);
mInjector.mElapsedRealtime += 1000;
mController.checkIdleStates(USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
index ced084717494..f8e740390291 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
import android.view.InputChannel;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -43,6 +44,7 @@ import org.junit.runner.RunWith;
* atest com.android.server.wm.TaskPositioningControllerTests
*/
@SmallTest
+@FlakyTest(bugId = 117924387)
@RunWith(AndroidJUnit4.class)
@Presubmit
public class TaskPositioningControllerTests extends WindowTestsBase {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 4e007c2d9929..3266b8b92a19 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1689,7 +1689,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception {
+ public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
List<String> associations = new ArrayList<>();
associations.add("a");
@@ -1703,7 +1703,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
+ public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
List<String> associations = new ArrayList<>();
when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
@@ -1721,6 +1721,38 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testGetNotificationChannelFromPrivilegedListener_assistant_success()
+ throws Exception {
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+
+ mBinderService.getNotificationChannelsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
+
+ verify(mPreferencesHelper, times(1)).getNotificationChannels(
+ anyString(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() throws Exception {
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
+
+ try {
+ mBinderService.getNotificationChannelsFromPrivilegedListener(
+ null, PKG, Process.myUserHandle());
+ fail("listeners that don't have a companion device shouldn't be able to call this");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mPreferencesHelper, never()).getNotificationChannels(
+ anyString(), anyInt(), anyBoolean());
+ }
+
+ @Test
public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
List<String> associations = new ArrayList<>();
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 4e997323a30e..bc54a5d2c499 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -320,14 +320,7 @@ public class AppIdleHistory {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory =
getPackageHistory(userHistory, packageName, elapsedRealtime, true);
- if (appUsageHistory == null) {
- return false; // Default to not idle
- } else {
- return appUsageHistory.currentBucket >= STANDBY_BUCKET_RARE;
- // Whether or not it's passed will now be externally calculated and the
- // bucket will be pushed to the history using setAppStandbyBucket()
- //return hasPassedThresholds(appUsageHistory, elapsedRealtime);
- }
+ return appUsageHistory.currentBucket >= STANDBY_BUCKET_RARE;
}
public AppUsageHistory getAppUsageHistory(String packageName, int userId,
@@ -404,17 +397,19 @@ public class AppIdleHistory {
public long getTimeSinceLastJobRun(String packageName, int userId, long elapsedRealtime) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory =
- getPackageHistory(userHistory, packageName, elapsedRealtime, true);
+ getPackageHistory(userHistory, packageName, elapsedRealtime, false);
// Don't adjust the default, else it'll wrap around to a positive value
- if (appUsageHistory.lastJobRunTime == Long.MIN_VALUE) return Long.MAX_VALUE;
+ if (appUsageHistory == null || appUsageHistory.lastJobRunTime == Long.MIN_VALUE) {
+ return Long.MAX_VALUE;
+ }
return getElapsedTime(elapsedRealtime) - appUsageHistory.lastJobRunTime;
}
public int getAppStandbyBucket(String packageName, int userId, long elapsedRealtime) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory =
- getPackageHistory(userHistory, packageName, elapsedRealtime, true);
- return appUsageHistory.currentBucket;
+ getPackageHistory(userHistory, packageName, elapsedRealtime, false);
+ return appUsageHistory == null ? STANDBY_BUCKET_NEVER : appUsageHistory.currentBucket;
}
public ArrayList<AppStandbyInfo> getAppStandbyBuckets(int userId, boolean appIdleEnabled) {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 02ad3a8772f8..6a74564367b8 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1161,6 +1161,10 @@ public class AppStandbyController {
void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
int reason, long elapsedRealtime, boolean resetTimeout) {
synchronized (mAppIdleLock) {
+ // If the package is not installed, don't allow the bucket to be set.
+ if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
+ return;
+ }
AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
userId, elapsedRealtime);
boolean predicted = (reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED;
@@ -1594,6 +1598,10 @@ public class AppStandbyController {
return mPackageManagerInternal.isPackageEphemeral(userId, packageName);
}
+ boolean isPackageInstalled(String packageName, int flags, int userId) {
+ return mPackageManagerInternal.getPackageUid(packageName, flags, userId) >= 0;
+ }
+
int[] getRunningUserIds() throws RemoteException {
return ActivityManager.getService().getRunningUserIds();
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 3127b3584dd9..d33a537f2194 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -676,7 +676,7 @@ public class TelecomManager {
/**
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static TelecomManager from(Context context) {
return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
}
diff --git a/telephony/java/android/telephony/RcsManager.java b/telephony/java/android/telephony/RcsManager.java
new file mode 100644
index 000000000000..00ce03a1f668
--- /dev/null
+++ b/telephony/java/android/telephony/RcsManager.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.IRcs;
+
+/**
+ * RcsManager is the application interface to RcsProvider and provides access methods to
+ * RCS related database tables.
+ * @hide - TODO make this public
+ */
+public class RcsManager {
+ private static final String TAG = "RcsManager";
+ private static final boolean VDBG = false;
+
+ /**
+ * Delete the RcsThread identified by the given threadId.
+ * @param threadId threadId of the thread to be deleted.
+ */
+ public void deleteThread(int threadId) {
+ if (VDBG) logd("deleteThread: threadId: " + threadId);
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ iRcs.deleteThread(threadId);
+ }
+ } catch (RemoteException re) {
+
+ }
+ }
+
+ private static void logd(String msg) {
+ Rlog.d(TAG, msg);
+ }
+}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index bfbcd5751bf4..e0ec2c50ab5b 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -21,7 +21,6 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -247,7 +246,7 @@ public class ServiceState implements Parcelable {
private String mDataOperatorAlphaLong;
private String mDataOperatorAlphaShort;
private String mDataOperatorNumeric;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private boolean mIsManualNetworkSelection;
private boolean mIsEmergencyOnly;
@@ -257,9 +256,9 @@ public class ServiceState implements Parcelable {
@UnsupportedAppUsage
private boolean mCssIndicator;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private int mNetworkId;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private int mSystemId;
@UnsupportedAppUsage
private int mCdmaRoamingIndicator;
@@ -457,7 +456,7 @@ public class ServiceState implements Parcelable {
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int getVoiceRegState() {
return mVoiceRegState;
}
@@ -472,7 +471,7 @@ public class ServiceState implements Parcelable {
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int getDataRegState() {
return mDataRegState;
}
@@ -533,7 +532,7 @@ public class ServiceState implements Parcelable {
* @return roaming status
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public boolean getVoiceRoaming() {
return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
@@ -557,7 +556,7 @@ public class ServiceState implements Parcelable {
* @return roaming type
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public boolean getDataRoaming() {
return getDataRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d0c6c49e18d6..3b4016437e9a 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1368,7 +1368,7 @@ public class SubscriptionManager {
}
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static int getPhoneId(int subId) {
if (!isValidSubscriptionId(subId)) {
if (DBG) {
@@ -1664,7 +1664,7 @@ public class SubscriptionManager {
* usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static boolean isUsableSubIdValue(int subId) {
return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
}
@@ -1682,7 +1682,7 @@ public class SubscriptionManager {
}
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
int[] subIds = SubscriptionManager.getSubId(phoneId);
if (subIds != null && subIds.length > 0) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5c5944ce988f..69901d297f42 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -232,8 +232,7 @@ public class TelephonyManager {
/** @hide
/* @deprecated - use getSystemService as described above */
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static TelephonyManager getDefault() {
return sInstance;
}
@@ -322,7 +321,7 @@ public class TelephonyManager {
}
/** {@hide} */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public static TelephonyManager from(Context context) {
return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
@@ -708,7 +707,7 @@ public class TelephonyManager {
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+ @UnsupportedAppUsage
public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
"android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
@@ -1766,7 +1765,7 @@ public class TelephonyManager {
}
/** {@hide} */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+ @UnsupportedAppUsage
private int getPhoneTypeFromProperty(int phoneId) {
String type = getTelephonyProperty(phoneId,
TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
@@ -1950,7 +1949,7 @@ public class TelephonyManager {
* @param subId
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getNetworkOperatorName(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
@@ -1978,7 +1977,7 @@ public class TelephonyManager {
* @param subId
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getNetworkOperator(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getNetworkOperatorForPhone(phoneId);
@@ -2302,7 +2301,7 @@ public class TelephonyManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int getDataNetworkType(int subId) {
try{
ITelephony telephony = getITelephony();
@@ -2338,7 +2337,7 @@ public class TelephonyManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int getVoiceNetworkType(int subId) {
try{
ITelephony telephony = getITelephony();
@@ -2821,7 +2820,7 @@ public class TelephonyManager {
* @param subId for which SimOperator is returned
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimOperator(int subId) {
return getSimOperatorNumeric(subId);
}
@@ -2835,7 +2834,7 @@ public class TelephonyManager {
* @see #getSimState
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimOperatorNumeric() {
int subId = mSubId;
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2864,7 +2863,7 @@ public class TelephonyManager {
* @param subId for which SimOperator is returned
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimOperatorNumeric(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getSimOperatorNumericForPhone(phoneId);
@@ -2878,7 +2877,7 @@ public class TelephonyManager {
* @param phoneId for which SimOperator is returned
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimOperatorNumericForPhone(int phoneId) {
return getTelephonyProperty(phoneId,
TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -2905,7 +2904,7 @@ public class TelephonyManager {
* @param subId for which SimOperatorName is returned
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimOperatorName(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getSimOperatorNameForPhone(phoneId);
@@ -2935,7 +2934,7 @@ public class TelephonyManager {
* @param subId for which SimCountryIso is returned
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSimCountryIso(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getSimCountryIsoForPhone(phoneId);
@@ -3147,7 +3146,7 @@ public class TelephonyManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getSubscriberId(int subId) {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -3532,7 +3531,7 @@ public class TelephonyManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public String getMsisdn(int subId) {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -4465,7 +4464,7 @@ public class TelephonyManager {
/**
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
@@ -8045,7 +8044,7 @@ public class TelephonyManager {
* either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public ServiceState getServiceStateForSubscriber(int subId) {
try {
ITelephony service = getITelephony();
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 7681aefc07dc..969959433f23 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -17,6 +17,8 @@
package android.telephony.ims.feature;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Message;
@@ -222,21 +224,31 @@ public class MmTelFeature extends ImsFeature {
* This MmTelFeature can then return the status of each of these capabilities (enabled or not)
* by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
* status can also be queried using {@link #queryCapabilityStatus()}.
+ * @see #isCapable(int)
*/
public static class MmTelCapabilities extends Capabilities {
/**
- * @hide
+ * Create a new empty {@link MmTelCapabilities} instance.
+ * @see #addCapabilities(int)
+ * @see #removeCapabilities(int)
*/
@VisibleForTesting
public MmTelCapabilities() {
super();
}
+ /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead.*/
+ @Deprecated
public MmTelCapabilities(Capabilities c) {
mCapabilities = c.mCapabilities;
}
+ /**
+ * Create a new {link @MmTelCapabilities} instance with the provided capabilities.
+ * @param capabilities The capabilities that are supported for MmTel in the form of a
+ * bitfield.
+ */
public MmTelCapabilities(int capabilities) {
mCapabilities = capabilities;
}
@@ -406,7 +418,10 @@ public class MmTelFeature extends ImsFeature {
* support the capability that is enabled. A capability that is disabled by the framework (via
* {@link #changeEnabledCapabilities}) should also show the status as disabled.
*/
- public final void notifyCapabilitiesStatusChanged(MmTelCapabilities c) {
+ public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) {
+ if (c == null) {
+ throw new IllegalArgumentException("MmTelCapabilities must be non-null!");
+ }
super.notifyCapabilitiesStatusChanged(c);
}
@@ -414,7 +429,12 @@ public class MmTelFeature extends ImsFeature {
* Notify the framework of an incoming call.
* @param c The {@link ImsCallSessionImplBase} of the new incoming call.
*/
- public final void notifyIncomingCall(ImsCallSessionImplBase c, Bundle extras) {
+ public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
+ @NonNull Bundle extras) {
+ if (c == null || extras == null) {
+ throw new IllegalArgumentException("ImsCallSessionImplBase and Bundle can not be "
+ + "null.");
+ }
synchronized (mLock) {
if (mListener == null) {
throw new IllegalStateException("Session is not available.");
@@ -434,7 +454,12 @@ public class MmTelFeature extends ImsFeature {
* This can be null if no call information is available for the rejected call.
* @param reason The {@link ImsReasonInfo} call rejection reason.
*/
- public final void notifyRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason) {
+ public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
+ @NonNull ImsReasonInfo reason) {
+ if (callProfile == null || reason == null) {
+ throw new IllegalArgumentException("ImsCallProfile and ImsReasonInfo must not be "
+ + "null.");
+ }
synchronized (mLock) {
if (mListener == null) {
throw new IllegalStateException("Session is not available.");
@@ -508,8 +533,8 @@ public class MmTelFeature extends ImsFeature {
* the framework.
*/
@Override
- public void changeEnabledCapabilities(CapabilityChangeRequest request,
- CapabilityCallbackProxy c) {
+ public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
+ @NonNull CapabilityCallbackProxy c) {
// Base implementation, no-op
}
@@ -531,7 +556,7 @@ public class MmTelFeature extends ImsFeature {
* {@link ImsCallProfile#CALL_TYPE_VS_RX}
* @return a {@link ImsCallProfile} object
*/
- public ImsCallProfile createCallProfile(int callSessionType, int callType) {
+ public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) {
// Base Implementation - Should be overridden
return null;
}
@@ -552,7 +577,7 @@ public class MmTelFeature extends ImsFeature {
*
* @param profile a call profile to make the call
*/
- public ImsCallSessionImplBase createCallSession(ImsCallProfile profile) {
+ public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) {
// Base Implementation - Should be overridden
return null;
}
@@ -569,7 +594,7 @@ public class MmTelFeature extends ImsFeature {
* @return a {@link ProcessCallResult} to the framework, which will be used to determine if the
* call will be placed over IMS or via CSFB.
*/
- public @ProcessCallResult int shouldProcessCall(String[] numbers) {
+ public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) {
return PROCESS_CALL_IMS;
}
@@ -602,7 +627,7 @@ public class MmTelFeature extends ImsFeature {
* @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service
* configuration.
*/
- public ImsUtImplBase getUt() {
+ public @NonNull ImsUtImplBase getUt() {
// Base Implementation - Should be overridden
return new ImsUtImplBase();
}
@@ -611,7 +636,7 @@ public class MmTelFeature extends ImsFeature {
* @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE
* calls that support it.
*/
- public ImsEcbmImplBase getEcbm() {
+ public @NonNull ImsEcbmImplBase getEcbm() {
// Base Implementation - Should be overridden
return new ImsEcbmImplBase();
}
@@ -620,7 +645,7 @@ public class MmTelFeature extends ImsFeature {
* @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event
* package processing for multi-endpoint.
*/
- public ImsMultiEndpointImplBase getMultiEndpoint() {
+ public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() {
// Base Implementation - Should be overridden
return new ImsMultiEndpointImplBase();
}
@@ -646,7 +671,7 @@ public class MmTelFeature extends ImsFeature {
* }
* }
*/
- public void setUiTtyMode(int mode, Message onCompleteMessage) {
+ public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) {
// Base Implementation - Should be overridden
}
@@ -680,7 +705,7 @@ public class MmTelFeature extends ImsFeature {
* @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS
* Provider.
*/
- public ImsSmsImplBase getSmsImplementation() {
+ public @NonNull ImsSmsImplBase getSmsImplementation() {
return new ImsSmsImplBase();
}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/com/android/internal/telephony/IRcs.aidl
new file mode 100644
index 000000000000..ede8695ef08e
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IRcs.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.telephony;
+
+interface IRcs {
+ void deleteThread(int threadId);
+} \ No newline at end of file