Merge "Minor improvements on DevicePolicyManagerService."
diff --git a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
index 29721c5..9e519f7 100644
--- a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
+++ b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
@@ -184,11 +184,11 @@
override fun startParsingPackage(
packageName: String,
- baseCodePath: String,
- codePath: String,
+ baseApkPath: String,
+ path: String,
manifestArray: TypedArray,
isCoreApp: Boolean
- ) = ParsingPackageImpl(packageName, baseCodePath, codePath, manifestArray)
+ ) = ParsingPackageImpl(packageName, baseApkPath, path, manifestArray)
})
override fun parseImpl(file: File) =
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index 2697428..a701f86 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -21,14 +21,12 @@
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
-import android.graphics.Rect;
import android.os.RemoteException;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.perftests.utils.PerfTestActivity;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
-import android.view.DisplayCutout;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.InsetsSourceControl;
@@ -38,6 +36,7 @@
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.widget.LinearLayout;
+import android.window.ClientWindowFrames;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
@@ -125,13 +124,7 @@
}
private static class RelayoutRunner {
- final Rect mOutFrame = new Rect();
- final Rect mOutContentInsets = new Rect();
- final Rect mOutVisibleInsets = new Rect();
- final Rect mOutStableInsets = new Rect();
- final Rect mOutBackDropFrame = new Rect();
- final DisplayCutout.ParcelableWrapper mOutDisplayCutout =
- new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
+ final ClientWindowFrames mOutFrames = new ClientWindowFrames();
final MergedConfiguration mOutMergedConfiguration = new MergedConfiguration();
final InsetsState mOutInsetsState = new InsetsState();
final InsetsSourceControl[] mOutControls = new InsetsSourceControl[0];
@@ -164,11 +157,9 @@
final IWindowSession session = WindowManagerGlobal.getWindowSession();
while (state.keepRunning()) {
session.relayout(mWindow, mSeq, mParams, mWidth, mHeight,
- mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame,
- mOutContentInsets, mOutVisibleInsets, mOutStableInsets,
- mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration,
- mOutSurfaceControl, mOutInsetsState, mOutControls, mOutSurfaceSize,
- mOutBlastSurfaceControl);
+ mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrames,
+ mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
+ mOutSurfaceSize, mOutBlastSurfaceControl);
}
}
}
diff --git a/apex/OWNERS b/apex/OWNERS
new file mode 100644
index 0000000..9760013
--- /dev/null
+++ b/apex/OWNERS
@@ -0,0 +1,7 @@
+# Shared module build rule owners
+per-file *.bp=hansson@google.com
+per-file *.bp=jiyong@google.com
+
+# This file, and all other OWNERS files
+per-file OWNERS=dariofreni@google.com
+per-file OWNERS=hansson@google.com
diff --git a/api/current.txt b/api/current.txt
index e678d16..723ffec5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6532,6 +6532,7 @@
method public android.graphics.Bitmap takeScreenshot();
method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
+ field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2
field public static final int ROTATION_FREEZE_0 = 0; // 0x0
field public static final int ROTATION_FREEZE_180 = 2; // 0x2
field public static final int ROTATION_FREEZE_270 = 3; // 0x3
@@ -31303,6 +31304,7 @@
@Deprecated public static class WifiConfiguration.GroupCipher {
field @Deprecated public static final int CCMP = 3; // 0x3
+ field @Deprecated public static final int GCMP_128 = 7; // 0x7
field @Deprecated public static final int GCMP_256 = 5; // 0x5
field @Deprecated public static final int SMS4 = 6; // 0x6
field @Deprecated public static final int TKIP = 2; // 0x2
@@ -31332,6 +31334,7 @@
@Deprecated public static class WifiConfiguration.PairwiseCipher {
field @Deprecated public static final int CCMP = 2; // 0x2
+ field @Deprecated public static final int GCMP_128 = 5; // 0x5
field @Deprecated public static final int GCMP_256 = 3; // 0x3
field @Deprecated public static final int NONE = 0; // 0x0
field @Deprecated public static final int SMS4 = 4; // 0x4
@@ -52845,6 +52848,7 @@
method public final boolean isFunctionPressed();
method public static final boolean isGamepadButton(int);
method public final boolean isLongPress();
+ method public static final boolean isMediaSessionKey(int);
method public final boolean isMetaPressed();
method public static boolean isModifierKey(int);
method public final boolean isNumLockOn();
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 806e266..c12d897 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -41,6 +41,10 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
+ public static final class MediaMetadata.Builder {
+ ctor public MediaMetadata.Builder(@NonNull android.media.MediaMetadata, @IntRange(from=1) int);
+ }
+
}
package android.media.session {
@@ -53,6 +57,10 @@
field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000
}
+ public static final class MediaSession.Token implements android.os.Parcelable {
+ method public int getUid();
+ }
+
public final class MediaSessionManager {
method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent);
diff --git a/api/system-current.txt b/api/system-current.txt
old mode 100755
new mode 100644
index 3ec3467..4134711
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -205,6 +205,7 @@
field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
+ field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
@@ -4337,6 +4338,14 @@
method @NonNull public android.media.HwAudioSource.Builder setAudioDeviceInfo(@NonNull android.media.AudioDeviceInfo);
}
+ public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
+ method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
+ }
+
+ public static interface MediaPlayer.OnImsRxNoticeListener {
+ method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
+ }
+
public final class MediaRecorder.AudioSource {
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int ECHO_REFERENCE = 1997; // 0x7cd
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public static final int HOTWORD = 1999; // 0x7cf
@@ -7343,6 +7352,7 @@
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public boolean is60GHzBandSupported();
method public boolean isApMacRandomizationSupported();
method public boolean isConnectedMacRandomizationSupported();
method @Deprecated public boolean isDeviceToDeviceRttSupported();
@@ -7582,6 +7592,7 @@
field public static final int WIFI_BAND_5_GHZ = 2; // 0x2
field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4
field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6
+ field public static final int WIFI_BAND_60_GHZ = 16; // 0x10
field public static final int WIFI_BAND_6_GHZ = 8; // 0x8
field public static final int WIFI_BAND_BOTH = 3; // 0x3
field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7
@@ -7821,6 +7832,8 @@
field public static final int BSS_CAPABILITY_CF_POLL_REQUEST = 8; // 0x8
field public static final int BSS_CAPABILITY_CHANNEL_AGILITY = 128; // 0x80
field public static final int BSS_CAPABILITY_DELAYED_BLOCK_ACK = 16384; // 0x4000
+ field public static final int BSS_CAPABILITY_DMG_ESS = 3; // 0x3
+ field public static final int BSS_CAPABILITY_DMG_IBSS = 1; // 0x1
field public static final int BSS_CAPABILITY_DSSS_OFDM = 8192; // 0x2000
field public static final int BSS_CAPABILITY_ESS = 1; // 0x1
field public static final int BSS_CAPABILITY_IBSS = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index 3de1d93..de2919b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -133,7 +133,6 @@
public class ActivityTaskManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void clearLaunchParamsForPackages(java.util.List<java.lang.String>);
method public static boolean currentUiModeSupportsErrorDialogs(@NonNull android.content.Context);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public String listAllStacks();
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void moveTaskToStack(int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException;
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5c08704..dec4a56 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -30,9 +30,8 @@
#include <binder/ProcessState.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <gui/SyncScreenCaptureListener.h>
+#include <gui/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicTypes.h>
@@ -182,18 +181,13 @@
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
- status_t result = ScreenshotClient::captureDisplay(displayId->value, captureListener);
+ ScreenCaptureResults captureResults;
+ status_t result = ScreenshotClient::captureDisplay(displayId->value, captureResults);
if (result != NO_ERROR) {
close(fd);
return 1;
}
- ScreenCaptureResults captureResults = captureListener->waitForResults();
- if (captureResults.result != NO_ERROR) {
- close(fd);
- return 1;
- }
ui::Dataspace dataspace = captureResults.capturedDataspace;
sp<GraphicBuffer> buffer = captureResults.buffer;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e6e22ba..94c2305 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -488,6 +488,8 @@
UIInteractionFrameInfoReported ui_interaction_frame_info_reported =
305 [(module) = "framework"];
UIActionLatencyReported ui_action_latency_reported = 306 [(module) = "framework"];
+ WifiDisconnectReported wifi_disconnect_reported = 307 [(module) = "wifi"];
+ WifiConnectionStateChanged wifi_connection_state_changed = 308 [(module) = "wifi"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -854,10 +856,10 @@
}
/**
- * Logs whether a wifi connection is successful and reasons for failure if it isn't.
+ * Logs whether a Wifi connection attempt was successful and reasons for failure if it wasn't.
*
* Logged from:
- * frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java
+ * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMetrics.java
*/
message WifiConnectionResultReported {
enum FailureCode {
@@ -869,13 +871,159 @@
FAILURE_DHCP = 5;
FAILURE_NETWORK_DISCONNECTION = 6;
FAILURE_ROAM_TIMEOUT = 7;
+ FAILURE_WRONG_PASSWORD = 8;
}
- // true represents a successful connection
+
+ enum Trigger {
+ UNKNOWN = 0;
+ // Connection attempt was initiated manually.
+ MANUAL = 1;
+ // Automatic reconnection to the same network as connected previously.
+ RECONNECT_SAME_NETWORK = 2;
+ // Automatic reconnection to a saved network, but not the previous one.
+ AUTOCONNECT_CONFIGURED_NETWORK = 3;
+ // Automatic first connection attempt after device boot.
+ AUTOCONNECT_BOOT = 4;
+ }
+
+ // True represents a successful connection.
optional bool connection_result = 1;
- // reason for the connection failure
+ // Reason for the connection failure.
optional FailureCode failure_code = 2;
- // scan rssi before the connection attempt
+ // Scan RSSI before the connection attempt.
optional int32 rssi = 3;
+ // Time taken by this connection attempt.
+ optional int32 connection_attempt_duration_millis = 4;
+ // Band bucket the connected network is on.
+ optional android.net.wifi.WifiBandBucket band = 5;
+ // Authentication type.
+ optional android.net.wifi.WifiAuthType auth_type = 6;
+ // What triggered this connection attempt.
+ optional Trigger trigger = 7;
+ // Whether this network was used (successfully connected to) previously.
+ optional bool network_used = 8;
+ // Time taken from the last successful connection (or device boot if that's the first one).
+ optional int32 time_since_last_connection_seconds = 9;
+}
+
+/**
+ * Logs when a Wifi connection drops.
+ *
+ * Logged from:
+ * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMetrics.java
+ */
+message WifiDisconnectReported {
+ enum FailureCode {
+ UNKNOWN = 0;
+
+ // Wifi supplicant failure reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ // See ISupplicantStaIfaceCallback.java:ReasonCode
+ UNSPECIFIED = 1;
+ PREV_AUTH_NOT_VALID = 2;
+ DEAUTH_LEAVING = 3;
+ DISASSOC_DUE_TO_INACTIVITY = 4;
+ DISASSOC_AP_BUSY = 5;
+ CLASS2_FRAME_FROM_NONAUTH_STA = 6;
+ CLASS3_FRAME_FROM_NONASSOC_STA = 7;
+ DISASSOC_STA_HAS_LEFT = 8;
+ STA_REQ_ASSOC_WITHOUT_AUTH = 9;
+ PWR_CAPABILITY_NOT_VALID = 10;
+ SUPPORTED_CHANNEL_NOT_VALID = 11;
+ BSS_TRANSITION_DISASSOC = 12;
+ INVALID_IE = 13;
+ MICHAEL_MIC_FAILURE = 14;
+ FOURWAY_HANDSHAKE_TIMEOUT = 15;
+ GROUP_KEY_UPDATE_TIMEOUT = 16;
+ IE_IN_4WAY_DIFFERS = 17;
+ GROUP_CIPHER_NOT_VALID = 18;
+ PAIRWISE_CIPHER_NOT_VALID = 19;
+ AKMP_NOT_VALID = 20;
+ UNSUPPORTED_RSN_IE_VERSION = 21;
+ INVALID_RSN_IE_CAPAB = 22;
+ IEEE_802_1X_AUTH_FAILED = 23;
+ CIPHER_SUITE_REJECTED = 24;
+ TDLS_TEARDOWN_UNREACHABLE = 25;
+ TDLS_TEARDOWN_UNSPECIFIED = 26;
+ SSP_REQUESTED_DISASSOC = 27;
+ NO_SSP_ROAMING_AGREEMENT = 28;
+ BAD_CIPHER_OR_AKM = 29;
+ NOT_AUTHORIZED_THIS_LOCATION = 30;
+ SERVICE_CHANGE_PRECLUDES_TS = 31;
+ UNSPECIFIED_QOS_REASON = 32;
+ NOT_ENOUGH_BANDWIDTH = 33;
+ DISASSOC_LOW_ACK = 34;
+ EXCEEDED_TXOP = 35;
+ STA_LEAVING = 36;
+ END_TS_BA_DLS = 37;
+ UNKNOWN_TS_BA = 38;
+ TIMEOUT = 39;
+ PEERKEY_MISMATCH = 45;
+ AUTHORIZED_ACCESS_LIMIT_REACHED = 46;
+ EXTERNAL_SERVICE_REQUIREMENTS = 47;
+ INVALID_FT_ACTION_FRAME_COUNT = 48;
+ INVALID_PMKID = 49;
+ INVALID_MDE = 50;
+ INVALID_FTE = 51;
+ MESH_PEERING_CANCELLED = 52;
+ MESH_MAX_PEERS = 53;
+ MESH_CONFIG_POLICY_VIOLATION = 54;
+ MESH_CLOSE_RCVD = 55;
+ MESH_MAX_RETRIES = 56;
+ MESH_CONFIRM_TIMEOUT = 57;
+ MESH_INVALID_GTK = 58;
+ MESH_INCONSISTENT_PARAMS = 59;
+ MESH_INVALID_SECURITY_CAP = 60;
+ MESH_PATH_ERROR_NO_PROXY_INFO = 61;
+ MESH_PATH_ERROR_NO_FORWARDING_INFO = 62;
+ MESH_PATH_ERROR_DEST_UNREACHABLE = 63;
+ MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64;
+ MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65;
+ MESH_CHANNEL_SWITCH_UNSPECIFIED = 66;
+
+ // ClientModeImpl error codes
+ // Defined in /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMetrics.java
+ IFACE_DESTROYED = 10000;
+ WIFI_DISABLED = 10001;
+ SUPPLICANT_DISCONNECTED = 10002;
+ CONNECTING_WATCHDOG_TIMER = 10003;
+ ROAM_WATCHDOG_TIMER = 10004;
+ }
+
+ // How long the session lasted from successful connection to disconnect.
+ optional int32 connected_duration_seconds = 1;
+
+ // Reason for the disconnect.
+ optional FailureCode failure_code = 2;
+
+ // Band bucket the connected network was on.
+ optional android.net.wifi.WifiBandBucket band = 3;
+
+ // Authentication type.
+ optional android.net.wifi.WifiAuthType auth_type = 4;
+
+ // Last seen RSSI before the disconnect.
+ optional int32 last_rssi = 5;
+
+ // Last seen link speed before the disconnect.
+ optional int32 last_link_speed = 6;
+}
+
+/**
+ * Logs when Wifi connection is established or dropped.
+ *
+ * Logged from:
+ * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMetrics.java
+ */
+message WifiConnectionStateChanged {
+ optional bool is_connected = 1;
+
+ // Band bucket the connected network was on.
+ // Filled for both connected and disconnected cases.
+ optional android.net.wifi.WifiBandBucket band = 2;
+
+ // Authentication type.
+ // Filled for both connected and disconnected cases.
+ optional android.net.wifi.WifiAuthType auth_type = 3;
}
/**
@@ -11239,4 +11387,4 @@
// List of leasees of this Blob
optional BlobLeaseeListProto leasees = 5 [(log_mode) = MODE_BYTES];
-}
+}
\ No newline at end of file
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 46c3770..8334b6b 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -315,6 +315,7 @@
}
int StatsPullerManager::ForceClearPullerCache() {
+ std::lock_guard<std::mutex> _l(mLock);
int totalCleared = 0;
for (const auto& pulledAtom : kAllPullAtomInfo) {
totalCleared += pulledAtom.second->ForceClearCache();
@@ -323,6 +324,7 @@
}
int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
+ std::lock_guard<std::mutex> _l(mLock);
int totalCleared = 0;
for (const auto& pulledAtom : kAllPullAtomInfo) {
totalCleared += pulledAtom.second->ClearCacheIfNecessary(timestampNs);
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 29260e9..45a0e87 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -24,8 +24,6 @@
parcelable ActivityManager.RunningServiceInfo;
parcelable ActivityManager.RunningTaskInfo;
/** @hide */
-parcelable ActivityManager.StackInfo;
-/** @hide */
parcelable ActivityManager.TaskThumbnail;
/** @hide */
parcelable ActivityManager.TaskSnapshot;
\ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a88c6a8..5aecb61 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -76,7 +76,6 @@
import android.util.Singleton;
import android.util.Size;
import android.view.Surface;
-import android.window.WindowContainerToken;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.procstats.ProcessStats;
@@ -2815,160 +2814,6 @@
}
/**
- * Information you can retrieve about an ActivityStack in the system.
- * @hide
- */
- public static class StackInfo implements Parcelable {
- @UnsupportedAppUsage
- public int stackId;
- @UnsupportedAppUsage
- public Rect bounds = new Rect();
- @UnsupportedAppUsage
- public int[] taskIds;
- @UnsupportedAppUsage
- public String[] taskNames;
- @UnsupportedAppUsage
- public Rect[] taskBounds;
- @UnsupportedAppUsage
- public int[] taskUserIds;
- @UnsupportedAppUsage
- public ComponentName topActivity;
- @UnsupportedAppUsage
- public int displayId;
- @UnsupportedAppUsage
- public int userId;
- @UnsupportedAppUsage
- public boolean visible;
- // Index of the stack in the display's stack list, can be used for comparison of stack order
- // TODO: Can be removed since no one is using it.
- @UnsupportedAppUsage
- @Deprecated
- public int position;
- public WindowContainerToken stackToken;
- /**
- * The full configuration the stack is currently running in.
- * @hide
- */
- final public Configuration configuration = new Configuration();
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(stackId);
- dest.writeInt(bounds.left);
- dest.writeInt(bounds.top);
- dest.writeInt(bounds.right);
- dest.writeInt(bounds.bottom);
- dest.writeIntArray(taskIds);
- dest.writeStringArray(taskNames);
- final int boundsCount = taskBounds == null ? 0 : taskBounds.length;
- dest.writeInt(boundsCount);
- for (int i = 0; i < boundsCount; i++) {
- dest.writeInt(taskBounds[i].left);
- dest.writeInt(taskBounds[i].top);
- dest.writeInt(taskBounds[i].right);
- dest.writeInt(taskBounds[i].bottom);
- }
- dest.writeIntArray(taskUserIds);
- dest.writeInt(displayId);
- dest.writeInt(userId);
- dest.writeInt(visible ? 1 : 0);
- dest.writeInt(position);
- stackToken.writeToParcel(dest, 0);
- if (topActivity != null) {
- dest.writeInt(1);
- topActivity.writeToParcel(dest, 0);
- } else {
- dest.writeInt(0);
- }
- configuration.writeToParcel(dest, flags);
- }
-
- public void readFromParcel(Parcel source) {
- stackId = source.readInt();
- bounds = new Rect(
- source.readInt(), source.readInt(), source.readInt(), source.readInt());
- taskIds = source.createIntArray();
- taskNames = source.createStringArray();
- final int boundsCount = source.readInt();
- if (boundsCount > 0) {
- taskBounds = new Rect[boundsCount];
- for (int i = 0; i < boundsCount; i++) {
- taskBounds[i] = new Rect();
- taskBounds[i].set(
- source.readInt(), source.readInt(), source.readInt(), source.readInt());
- }
- } else {
- taskBounds = null;
- }
- taskUserIds = source.createIntArray();
- displayId = source.readInt();
- userId = source.readInt();
- visible = source.readInt() > 0;
- position = source.readInt();
- stackToken = WindowContainerToken.CREATOR.createFromParcel(source);
- if (source.readInt() > 0) {
- topActivity = ComponentName.readFromParcel(source);
- }
- configuration.readFromParcel(source);
- }
-
- public static final @android.annotation.NonNull Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
- @Override
- public StackInfo createFromParcel(Parcel source) {
- return new StackInfo(source);
- }
- @Override
- public StackInfo[] newArray(int size) {
- return new StackInfo[size];
- }
- };
-
- public StackInfo() {
- }
-
- private StackInfo(Parcel source) {
- readFromParcel(source);
- }
-
- @UnsupportedAppUsage
- public String toString(String prefix) {
- StringBuilder sb = new StringBuilder(256);
- sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
- sb.append(" bounds="); sb.append(bounds.toShortString());
- sb.append(" displayId="); sb.append(displayId);
- sb.append(" userId="); sb.append(userId);
- sb.append("\n");
- sb.append(" configuration="); sb.append(configuration);
- sb.append("\n");
- prefix = prefix + " ";
- for (int i = 0; i < taskIds.length; ++i) {
- sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);
- sb.append(": "); sb.append(taskNames[i]);
- if (taskBounds != null) {
- sb.append(" bounds="); sb.append(taskBounds[i].toShortString());
- }
- sb.append(" userId=").append(taskUserIds[i]);
- sb.append(" visible=").append(visible);
- if (topActivity != null) {
- sb.append(" topActivity=").append(topActivity);
- }
- sb.append("\n");
- }
- return sb.toString();
- }
-
- @Override
- public String toString() {
- return toString("");
- }
- }
-
- /**
* @hide
*/
@RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA,
diff --git a/core/java/android/app/ActivityTaskManager.aidl b/core/java/android/app/ActivityTaskManager.aidl
new file mode 100644
index 0000000..a12bcd5
--- /dev/null
+++ b/core/java/android/app/ActivityTaskManager.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/** @hide */
+parcelable ActivityTaskManager.RootTaskInfo;
\ No newline at end of file
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 4283d7a..3e4d5ee 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -29,6 +29,8 @@
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.DisplayMetrics;
@@ -391,27 +393,6 @@
}
/**
- * List all activity stacks information.
- */
- @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public String listAllStacks() {
- final List<ActivityManager.StackInfo> stacks;
- try {
- stacks = getService().getAllStackInfos();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- final StringBuilder sb = new StringBuilder();
- if (stacks != null) {
- for (ActivityManager.StackInfo info : stacks) {
- sb.append(info).append("\n");
- }
- }
- return sb.toString();
- }
-
- /**
* Clears launch params for the given package.
* @param packageNames the names of the packages of which the launch params are to be cleared
*/
@@ -468,4 +449,96 @@
final Configuration config = context.getResources().getConfiguration();
return currentUiModeSupportsErrorDialogs(config);
}
+
+ /**
+ * Information you can retrieve about a root task in the system.
+ * @hide
+ */
+ public static class RootTaskInfo extends TaskInfo implements Parcelable {
+ // TODO(b/148895075): Move some of the fields to TaskInfo.
+ public Rect bounds = new Rect();
+ public int[] childTaskIds;
+ public String[] childTaskNames;
+ public Rect[] childTaskBounds;
+ public int[] childTaskUserIds;
+ public boolean visible;
+ // Index of the stack in the display's stack list, can be used for comparison of stack order
+ public int position;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeTypedObject(bounds, flags);
+ dest.writeIntArray(childTaskIds);
+ dest.writeStringArray(childTaskNames);
+ dest.writeTypedArray(childTaskBounds, flags);
+ dest.writeIntArray(childTaskUserIds);
+ dest.writeInt(visible ? 1 : 0);
+ dest.writeInt(position);
+ super.writeToParcel(dest, flags);
+ }
+
+ @Override
+ void readFromParcel(Parcel source) {
+ bounds = source.readTypedObject(Rect.CREATOR);
+ childTaskIds = source.createIntArray();
+ childTaskNames = source.createStringArray();
+ childTaskBounds = source.createTypedArray(Rect.CREATOR);
+ childTaskUserIds = source.createIntArray();
+ visible = source.readInt() > 0;
+ position = source.readInt();
+ super.readFromParcel(source);
+ }
+
+ public static final @NonNull Creator<RootTaskInfo> CREATOR = new Creator<>() {
+ @Override
+ public RootTaskInfo createFromParcel(Parcel source) {
+ return new RootTaskInfo(source);
+ }
+
+ @Override
+ public RootTaskInfo[] newArray(int size) {
+ return new RootTaskInfo[size];
+ }
+ };
+
+ public RootTaskInfo() {
+ }
+
+ private RootTaskInfo(Parcel source) {
+ readFromParcel(source);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(256);
+ sb.append("RootTask id="); sb.append(taskId);
+ sb.append(" bounds="); sb.append(bounds.toShortString());
+ sb.append(" displayId="); sb.append(displayId);
+ sb.append(" userId="); sb.append(userId);
+ sb.append("\n");
+
+ sb.append(" configuration="); sb.append(configuration);
+ sb.append("\n");
+
+ for (int i = 0; i < childTaskIds.length; ++i) {
+ sb.append(" taskId="); sb.append(childTaskIds[i]);
+ sb.append(": "); sb.append(childTaskNames[i]);
+ if (childTaskBounds != null) {
+ sb.append(" bounds="); sb.append(childTaskBounds[i].toShortString());
+ }
+ sb.append(" userId=").append(childTaskUserIds[i]);
+ sb.append(" visible=").append(visible);
+ if (topActivity != null) {
+ sb.append(" topActivity=").append(topActivity);
+ }
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index cd9e02d..45b25a3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -17,6 +17,7 @@
package android.app;
import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.app.ContentProviderHolder;
@@ -99,7 +100,6 @@
void unregisterUidObserver(in IUidObserver observer);
boolean isUidActive(int uid, String callingPackage);
int getUidProcessState(int uid, in String callingPackage);
- boolean setSchedPolicyCgroup(int tid, int group);
// =============== End of transactions used on native side as well ============================
// Special low-level communication with activity manager.
@@ -449,12 +449,11 @@
@UnsupportedAppUsage
void hang(in IBinder who, boolean allowRestart);
- @UnsupportedAppUsage
- List<ActivityManager.StackInfo> getAllStackInfos();
+ List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfos();
@UnsupportedAppUsage
void moveTaskToStack(int taskId, int stackId, boolean toTop);
void setFocusedStack(int stackId);
- ActivityManager.StackInfo getFocusedStackInfo();
+ ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo();
@UnsupportedAppUsage
void restart();
void performIdleMaintenance();
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 72a3637d..f3c7fe94 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -17,6 +17,7 @@
package android.app;
import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
import android.app.ApplicationErrorReport;
import android.app.ContentProviderHolder;
import android.app.GrantedUriPermission;
@@ -186,7 +187,7 @@
in AssistStructure structure, in AssistContent content, in Uri referrer);
void setFocusedStack(int stackId);
- ActivityManager.StackInfo getFocusedStackInfo();
+ ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo();
Rect getTaskBounds(int taskId);
void cancelRecentsAnimation(boolean restoreHomeStackPosition);
@@ -260,11 +261,10 @@
/** Removes stack of the activity types from the system. */
void removeStacksWithActivityTypes(in int[] activityTypes);
- List<ActivityManager.StackInfo> getAllStackInfos();
- ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType);
- List<ActivityManager.StackInfo> getAllStackInfosOnDisplay(int displayId);
- ActivityManager.StackInfo getStackInfoOnDisplay(int windowingMode, int activityType,
- int displayId);
+ List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfos();
+ ActivityTaskManager.RootTaskInfo getRootTaskInfo(int windowingMode, int activityType);
+ List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId);
+ ActivityTaskManager.RootTaskInfo getRootTaskInfoOnDisplay(int windowingMode, int activityType, int displayId);
/**
* Informs ActivityTaskManagerService that the keyguard is showing.
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 2ef147b..f2a9daa 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -97,7 +97,8 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
+ @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES,
+ UiAutomation.FLAG_DONT_USE_ACCESSIBILITY})
public @interface UiAutomationFlags {};
@@ -2170,7 +2171,8 @@
* </p>
*
* @param flags The flags to be passed to the UiAutomation, for example
- * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
+ * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES},
+ * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY}.
*
* @return The UI automation instance.
*
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index f3f00e5..4718cf1 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -36,7 +36,8 @@
private static final String TAG = "TaskInfo";
/**
- * The id of the user the task was running as.
+ * The id of the user the task was running as if this is a leaf task. The id of the current
+ * running user of the system otherwise.
* @hide
*/
@UnsupportedAppUsage
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 109205f..ab997e9 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -56,6 +56,7 @@
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.function.pooled.PooledLambda;
import libcore.io.IoUtils;
@@ -142,13 +143,22 @@
}
/**
- * UiAutomation supresses accessibility services by default. This flag specifies that
+ * UiAutomation suppresses accessibility services by default. This flag specifies that
* existing accessibility services should continue to run, and that new ones may start.
* This flag is set when obtaining the UiAutomation from
* {@link Instrumentation#getUiAutomation(int)}.
*/
public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 0x00000001;
+ /**
+ * UiAutomation uses the accessibility subsystem by default. This flag provides an option to
+ * eliminate the overhead of engaging the accessibility subsystem for tests that do not need to
+ * interact with the user interface. Setting this flag disables methods that rely on
+ * accessibility. This flag is set when obtaining the UiAutomation from
+ * {@link Instrumentation#getUiAutomation(int)}.
+ */
+ public static final int FLAG_DONT_USE_ACCESSIBILITY = 0x00000002;
+
private final Object mLock = new Object();
private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>();
@@ -267,11 +277,14 @@
/**
* Connects this UiAutomation to the accessibility introspection APIs.
*
- * @param flags Any flags to apply to the automation as it gets connected
+ * @param flags Any flags to apply to the automation as it gets connected while
+ * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY} would keep the
+ * connection disconnected and not to register UiAutomation service.
* @param timeoutMillis The wait timeout in milliseconds
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is already
+ * established.
* @throws TimeoutException If not connected within the timeout
- *
* @hide
*/
public void connectWithTimeout(int flags, long timeoutMillis) throws TimeoutException {
@@ -292,6 +305,12 @@
// Calling out without a lock held.
mUiAutomationConnection.connect(mClient, flags);
mFlags = flags;
+ // If UiAutomation is not allowed to use the accessibility subsystem, the
+ // connection state should keep disconnected and not to start the client connection.
+ if (!useAccessibility()) {
+ mConnectionState = ConnectionState.DISCONNECTED;
+ return;
+ }
} catch (RemoteException re) {
throw new RuntimeException("Error while connecting " + this, re);
}
@@ -340,7 +359,7 @@
throw new IllegalStateException(
"Cannot call disconnect() while connecting " + this);
}
- if (mConnectionState == ConnectionState.DISCONNECTED) {
+ if (useAccessibility() && mConnectionState == ConnectionState.DISCONNECTED) {
return;
}
mConnectionState = ConnectionState.DISCONNECTED;
@@ -354,8 +373,10 @@
} catch (RemoteException re) {
throw new RuntimeException("Error while disconnecting " + this, re);
} finally {
- mRemoteCallbackThread.quit();
- mRemoteCallbackThread = null;
+ if (mRemoteCallbackThread != null) {
+ mRemoteCallbackThread.quit();
+ mRemoteCallbackThread = null;
+ }
}
}
@@ -389,9 +410,13 @@
* The callbacks are delivered on the main application thread.
*
* @param listener The callback.
+ *
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public void setOnAccessibilityEventListener(OnAccessibilityEventListener listener) {
synchronized (mLock) {
+ throwIfNotConnectedLocked();
mOnAccessibilityEventListener = listener;
}
}
@@ -423,9 +448,6 @@
* @see #dropShellPermissionIdentity()
*/
public void adoptShellPermissionIdentity() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
// Calling out without a lock held.
mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), null);
@@ -451,9 +473,6 @@
* @see #dropShellPermissionIdentity()
*/
public void adoptShellPermissionIdentity(@Nullable String... permissions) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
// Calling out without a lock held.
mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), permissions);
@@ -470,9 +489,6 @@
* @see #adoptShellPermissionIdentity()
*/
public void dropShellPermissionIdentity() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
// Calling out without a lock held.
mUiAutomationConnection.dropShellPermissionIdentity();
@@ -489,6 +505,8 @@
* @param action The action to perform.
* @return Whether the action was successfully performed.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK
* @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_HOME
* @see android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS
@@ -523,13 +541,18 @@
* </p>
*
* @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
- * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
+ * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
* @return The node info of the focused view or null.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see AccessibilityNodeInfo#FOCUS_INPUT
* @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
*/
public AccessibilityNodeInfo findFocus(int focus) {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
}
@@ -541,6 +564,8 @@
*
* @return The accessibility service info.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see AccessibilityServiceInfo
*/
public final AccessibilityServiceInfo getServiceInfo() {
@@ -567,6 +592,8 @@
*
* @param info The info.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see AccessibilityServiceInfo
*/
public final void setServiceInfo(AccessibilityServiceInfo info) {
@@ -602,6 +629,8 @@
* </p>
*
* @return The windows if there are windows such, otherwise an empty list.
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public List<AccessibilityWindowInfo> getWindows() {
final int connectionId;
@@ -630,6 +659,8 @@
*
* @return The windows of all displays if there are windows and the service is can retrieve
* them, otherwise an empty list. The key of SparseArray is display ID.
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
@NonNull
public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
@@ -647,6 +678,8 @@
* Gets the root {@link AccessibilityNodeInfo} in the active window.
*
* @return The root info.
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public AccessibilityNodeInfo getRootInActiveWindow() {
final int connectionId;
@@ -664,14 +697,12 @@
* <p>
* <strong>Note:</strong> It is caller's responsibility to recycle the event.
* </p>
+ *
* @param event The event to inject.
* @param sync Whether to inject the event synchronously.
* @return Whether event injection succeeded.
*/
public boolean injectInputEvent(InputEvent event, boolean sync) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
if (DEBUG) {
Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync);
@@ -692,9 +723,6 @@
*/
@TestApi
public void syncInputTransactions() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
// Calling out without a lock held.
mUiAutomationConnection.syncInputTransactions();
@@ -720,9 +748,6 @@
* @see #ROTATION_UNFREEZE
*/
public boolean setRotation(int rotation) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
switch (rotation) {
case ROTATION_FREEZE_0:
case ROTATION_FREEZE_90:
@@ -752,11 +777,14 @@
* <p>
* <strong>Note:</strong> It is caller's responsibility to recycle the returned event.
* </p>
+ *
* @param command The command to execute.
* @param filter Filter that recognizes the expected event.
* @param timeoutMillis The wait timeout in milliseconds.
*
* @throws TimeoutException If the expected event is not received within the timeout.
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public AccessibilityEvent executeAndWaitForEvent(Runnable command,
AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException {
@@ -845,6 +873,8 @@
*
* @throws TimeoutException If no idle state was detected within
* <code>globalTimeoutMillis.</code>
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
*/
public void waitForIdle(long idleTimeoutMillis, long globalTimeoutMillis)
throws TimeoutException {
@@ -874,9 +904,9 @@
return;
}
try {
- mLock.wait(remainingIdleTimeMillis);
+ mLock.wait(remainingIdleTimeMillis);
} catch (InterruptedException ie) {
- /* ignore */
+ /* ignore */
}
}
}
@@ -888,9 +918,6 @@
* @return The screenshot bitmap on success, null otherwise.
*/
public Bitmap takeScreenshot() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
Display display = DisplayManagerGlobal.getInstance()
.getRealDisplay(Display.DEFAULT_DISPLAY);
Point displaySize = new Point();
@@ -927,9 +954,6 @@
* @see ActivityManager#isUserAMonkey()
*/
public void setRunAsMonkey(boolean enable) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
ActivityManager.getService().setUserIsMonkey(enable);
} catch (RemoteException re) {
@@ -946,6 +970,8 @@
* @return Whether the window is present and its frame statistics
* were cleared.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see android.view.WindowContentFrameStats
* @see #getWindowContentFrameStats(int)
* @see #getWindows()
@@ -991,6 +1017,8 @@
* @param windowId The window id.
* @return The window frame statistics, or null if the window is not present.
*
+ * @throws IllegalStateException If the connection to the accessibility subsystem is not
+ * established.
* @see android.view.WindowContentFrameStats
* @see #clearWindowContentFrameStats(int)
* @see #getWindows()
@@ -1022,9 +1050,6 @@
* @see android.R.styleable#WindowAnimation
*/
public void clearWindowAnimationFrameStats() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
if (DEBUG) {
Log.i(LOG_TAG, "Clearing window animation frame stats");
@@ -1064,9 +1089,6 @@
* @see android.R.styleable#WindowAnimation
*/
public WindowAnimationFrameStats getWindowAnimationFrameStats() {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
if (DEBUG) {
Log.i(LOG_TAG, "Getting window animation frame stats");
@@ -1081,6 +1103,7 @@
/**
* Grants a runtime permission to a package.
+ *
* @param packageName The package to which to grant.
* @param permission The permission to grant.
* @throws SecurityException if unable to grant the permission.
@@ -1104,15 +1127,13 @@
/**
* Grants a runtime permission to a package for a user.
+ *
* @param packageName The package to which to grant.
* @param permission The permission to grant.
* @throws SecurityException if unable to grant the permission.
*/
public void grantRuntimePermissionAsUser(String packageName, String permission,
UserHandle userHandle) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
if (DEBUG) {
Log.i(LOG_TAG, "Granting runtime permission");
@@ -1127,6 +1148,7 @@
/**
* Revokes a runtime permission from a package.
+ *
* @param packageName The package to which to grant.
* @param permission The permission to grant.
* @throws SecurityException if unable to revoke the permission.
@@ -1150,15 +1172,13 @@
/**
* Revokes a runtime permission from a package.
+ *
* @param packageName The package to which to grant.
* @param permission The permission to grant.
* @throws SecurityException if unable to revoke the permission.
*/
public void revokeRuntimePermissionAsUser(String packageName, String permission,
UserHandle userHandle) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
try {
if (DEBUG) {
Log.i(LOG_TAG, "Revoking runtime permission");
@@ -1186,9 +1206,6 @@
* @see #adoptShellPermissionIdentity()
*/
public ParcelFileDescriptor executeShellCommand(String command) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
warnIfBetterCommand(command);
ParcelFileDescriptor source = null;
@@ -1229,9 +1246,6 @@
*/
@TestApi
public ParcelFileDescriptor[] executeShellCommandRw(String command) {
- synchronized (mLock) {
- throwIfNotConnectedLocked();
- }
warnIfBetterCommand(command);
ParcelFileDescriptor source_read = null;
@@ -1276,15 +1290,21 @@
return stringBuilder.toString();
}
+ @GuardedBy("mLock")
private void throwIfConnectedLocked() {
if (mConnectionState == ConnectionState.CONNECTED) {
throw new IllegalStateException("UiAutomation connected, " + this);
}
}
+ @GuardedBy("mLock")
private void throwIfNotConnectedLocked() {
if (mConnectionState != ConnectionState.CONNECTED) {
- throw new IllegalStateException("UiAutomation not connected, " + this);
+ final String msg = useAccessibility()
+ ? "UiAutomation not connected, "
+ : "UiAutomation not connected: Accessibility-dependent method called with "
+ + "FLAG_DONT_USE_ACCESSIBILITY set, ";
+ throw new IllegalStateException(msg + this);
}
}
@@ -1298,11 +1318,16 @@
}
}
+ private boolean useAccessibility() {
+ return (mFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0;
+ }
+
private class IAccessibilityServiceClientImpl extends IAccessibilityServiceClientWrapper {
public IAccessibilityServiceClientImpl(Looper looper, int generationId) {
super(null, looper, new Callbacks() {
private final int mGenerationId = generationId;
+
/**
* True if UiAutomation doesn't interact with this client anymore.
* Used by methods below to stop sending notifications or changing members
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 0e6a063..3522b1b 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -199,7 +199,7 @@
public static final int NOTIFICATION_INTERRUPTION = 12;
/**
- * A Slice was pinned by the default assistant.
+ * A Slice was pinned by the default launcher or the default assistant.
* @hide
*/
@SystemApi
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index b434072..eec7c9c 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -343,20 +343,22 @@
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
- * @param attributionTag attribution tag of caller (if not self)
+ * @param callingPackageName package name tag of caller (if not self)
+ * @param callingAttributionTag attribution tag of caller (if not self)
* @param message A message describing the reason the permission was checked
*
* @see #checkCallingOrSelfPermissionForPreflight(Context, String)
*/
@PermissionResult
public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
- @NonNull String permission, @Nullable String attributionTag, @Nullable String message) {
- String packageName = (Binder.getCallingPid() == Process.myPid())
- ? context.getPackageName() : null;
- attributionTag = (Binder.getCallingPid() == Process.myPid())
- ? context.getAttributionTag() : attributionTag;
+ @NonNull String permission, @Nullable String callingPackageName,
+ @Nullable String callingAttributionTag, @Nullable String message) {
+ callingPackageName = (Binder.getCallingPid() == Process.myPid())
+ ? context.getPackageName() : callingPackageName;
+ callingAttributionTag = (Binder.getCallingPid() == Process.myPid())
+ ? context.getAttributionTag() : callingAttributionTag;
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, attributionTag, message);
+ Binder.getCallingUid(), callingPackageName, callingAttributionTag, message);
}
/**
@@ -375,15 +377,15 @@
* app's fg/gb state) and this check will not leave a trace that permission protected
* data was delivered. When you are about to deliver the location data to a registered
* listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
- * String, String, String)} which will evaluate the permission access based on the current
- * fg/bg state of the app and leave a record that the data was accessed.
+ * String, String, String, String)} which will evaluate the permission access based on the
+ * current fg/bg state of the app and leave a record that the data was accessed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
*
- * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String)
+ * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String, String)
*/
@PermissionResult
public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 542cfc2..6d92d3e 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -53,7 +53,7 @@
/** @hide */
public class ApkLiteParseUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
// TODO(b/135203078): Consolidate constants
private static final int DEFAULT_MIN_SDK_VERSION = 1;
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index e450748..e573539 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -579,8 +579,8 @@
ii.handleProfiling = i.isHandleProfiling();
ii.functionalTest = i.isFunctionalTest();
- ii.sourceDir = pkg.getBaseCodePath();
- ii.publicSourceDir = pkg.getBaseCodePath();
+ ii.sourceDir = pkg.getBaseApkPath();
+ ii.publicSourceDir = pkg.getBaseApkPath();
ii.splitNames = pkg.getSplitNames();
ii.splitSourceDirs = pkg.getSplitCodePaths();
ii.splitPublicSourceDirs = pkg.getSplitCodePaths();
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 0c0dc31..ed12a17 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -145,7 +145,7 @@
private String realPackage;
@NonNull
- protected String baseCodePath;
+ protected String mBaseApkPath;
private boolean requiredForAllUsers;
@Nullable
@@ -280,7 +280,7 @@
@NonNull
@DataClass.ParcelWith(ForInternedString.class)
- protected String codePath;
+ protected String mPath;
private boolean use32BitAbi;
private boolean visibleToInstantApps;
@@ -429,11 +429,11 @@
private ArraySet<String> mimeGroups;
@VisibleForTesting
- public ParsingPackageImpl(@NonNull String packageName, @NonNull String baseCodePath,
- @NonNull String codePath, @Nullable TypedArray manifestArray) {
+ public ParsingPackageImpl(@NonNull String packageName, @NonNull String baseApkPath,
+ @NonNull String path, @Nullable TypedArray manifestArray) {
this.packageName = TextUtils.safeIntern(packageName);
- this.baseCodePath = baseCodePath;
- this.codePath = codePath;
+ this.mBaseApkPath = baseApkPath;
+ this.mPath = path;
if (manifestArray != null) {
versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0);
@@ -888,6 +888,9 @@
public ApplicationInfo toAppInfoWithoutStateWithoutFlags() {
ApplicationInfo appInfo = new ApplicationInfo();
+ // Lines that are commented below are state related and should not be assigned here.
+ // They are left in as placeholders, since there is no good backwards compatible way to
+ // separate these.
appInfo.appComponentFactory = appComponentFactory;
appInfo.backupAgentName = backupAgentName;
appInfo.banner = banner;
@@ -897,13 +900,17 @@
appInfo.compatibleWidthLimitDp = compatibleWidthLimitDp;
appInfo.compileSdkVersion = compileSdkVersion;
appInfo.compileSdkVersionCodename = compileSdkVersionCodeName;
-// appInfo.credentialProtectedDataDir = credentialProtectedDataDir;
-// appInfo.dataDir = dataDir;
+// appInfo.credentialProtectedDataDir
+ appInfo.crossProfile = isCrossProfile();
+// appInfo.dataDir
appInfo.descriptionRes = descriptionRes;
-// appInfo.deviceProtectedDataDir = deviceProtectedDataDir;
+// appInfo.deviceProtectedDataDir
appInfo.enabled = enabled;
+// appInfo.enabledSetting
appInfo.fullBackupContent = fullBackupContent;
-// appInfo.hiddenUntilInstalled = hiddenUntilInstalled;
+ // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
+// appInfo.mHiddenApiPolicy
+// appInfo.hiddenUntilInstalled
appInfo.icon = (PackageParser.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;
appInfo.iconRes = iconRes;
appInfo.roundIconRes = roundIconRes;
@@ -920,9 +927,9 @@
if (appInfo.name != null) {
appInfo.name = appInfo.name.trim();
}
-// appInfo.nativeLibraryDir = nativeLibraryDir;
-// appInfo.nativeLibraryRootDir = nativeLibraryRootDir;
-// appInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
+// appInfo.nativeLibraryDir
+// appInfo.nativeLibraryRootDir
+// appInfo.nativeLibraryRootRequiresIsa
appInfo.networkSecurityConfigRes = networkSecurityConfigRes;
appInfo.nonLocalizedLabel = nonLocalizedLabel;
if (appInfo.nonLocalizedLabel != null) {
@@ -930,16 +937,17 @@
}
appInfo.packageName = packageName;
appInfo.permission = permission;
-// appInfo.primaryCpuAbi = primaryCpuAbi;
+// appInfo.primaryCpuAbi
appInfo.processName = getProcessName();
appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp;
-// appInfo.secondaryCpuAbi = secondaryCpuAbi;
-// appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-// appInfo.seInfo = seInfo;
-// appInfo.seInfoUser = seInfoUser;
-// appInfo.sharedLibraryFiles = usesLibraryFiles.isEmpty()
-// ? null : usesLibraryFiles.toArray(new String[0]);
-// appInfo.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+// appInfo.resourceDirs
+// appInfo.secondaryCpuAbi
+// appInfo.secondaryNativeLibraryDir
+// appInfo.seInfo
+// appInfo.seInfoUser
+// appInfo.sharedLibraryFiles
+// appInfo.sharedLibraryInfos
+// appInfo.showUserIcon
appInfo.splitClassLoaderNames = splitClassLoaderNames;
appInfo.splitDependencies = splitDependencies;
appInfo.splitNames = splitNames;
@@ -948,29 +956,19 @@
appInfo.targetSdkVersion = targetSdkVersion;
appInfo.taskAffinity = taskAffinity;
appInfo.theme = theme;
-// appInfo.uid = uid;
+// appInfo.uid
appInfo.uiOptions = uiOptions;
appInfo.volumeUuid = volumeUuid;
appInfo.zygotePreloadName = zygotePreloadName;
- appInfo.crossProfile = isCrossProfile();
appInfo.setGwpAsanMode(gwpAsanMode);
- appInfo.setBaseCodePath(baseCodePath);
- appInfo.setBaseResourcePath(baseCodePath);
- appInfo.setCodePath(codePath);
- appInfo.setResourcePath(codePath);
+ appInfo.setBaseCodePath(mBaseApkPath);
+ appInfo.setBaseResourcePath(mBaseApkPath);
+ appInfo.setCodePath(mPath);
+ appInfo.setResourcePath(mPath);
appInfo.setSplitCodePaths(splitCodePaths);
appInfo.setSplitResourcePaths(splitCodePaths);
appInfo.setVersionCode(PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode));
- // TODO(b/135203078): Can this be removed? Looks only used in ActivityInfo.
-// appInfo.showUserIcon = pkg.getShowUserIcon();
- // TODO(b/135203078): Unused?
-// appInfo.resourceDirs = pkg.getResourceDirs();
- // TODO(b/135203078): Unused?
-// appInfo.enabledSetting = pkg.getEnabledSetting();
- // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
-// appInfo.mHiddenApiPolicy = pkg.getHiddenApiPolicy();
-
return appInfo;
}
@@ -995,7 +993,7 @@
dest.writeString(this.compileSdkVersionCodeName);
sForInternedString.parcel(this.packageName, dest, flags);
dest.writeString(this.realPackage);
- dest.writeString(this.baseCodePath);
+ dest.writeString(this.mBaseApkPath);
dest.writeBoolean(this.requiredForAllUsers);
dest.writeString(this.restrictedAccountType);
dest.writeString(this.requiredAccountType);
@@ -1050,7 +1048,7 @@
dest.writeBundle(this.metaData);
sForInternedString.parcel(this.volumeUuid, dest, flags);
dest.writeParcelable(this.signingDetails, flags);
- dest.writeString(this.codePath);
+ dest.writeString(this.mPath);
dest.writeBoolean(this.use32BitAbi);
dest.writeBoolean(this.visibleToInstantApps);
dest.writeBoolean(this.forceQueryable);
@@ -1159,7 +1157,7 @@
this.compileSdkVersionCodeName = in.readString();
this.packageName = sForInternedString.unparcel(in);
this.realPackage = in.readString();
- this.baseCodePath = in.readString();
+ this.mBaseApkPath = in.readString();
this.requiredForAllUsers = in.readBoolean();
this.restrictedAccountType = in.readString();
this.requiredAccountType = in.readString();
@@ -1214,7 +1212,7 @@
this.metaData = in.readBundle(boot);
this.volumeUuid = sForInternedString.unparcel(in);
this.signingDetails = in.readParcelable(boot);
- this.codePath = in.readString();
+ this.mPath = in.readString();
this.use32BitAbi = in.readBoolean();
this.visibleToInstantApps = in.readBoolean();
this.forceQueryable = in.readBoolean();
@@ -1363,8 +1361,8 @@
@NonNull
@Override
- public String getBaseCodePath() {
- return baseCodePath;
+ public String getBaseApkPath() {
+ return mBaseApkPath;
}
@Override
@@ -1649,8 +1647,8 @@
@NonNull
@Override
- public String getCodePath() {
- return codePath;
+ public String getPath() {
+ return mPath;
}
@Override
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index 7e0fe7d..dbd15f5 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -548,7 +548,7 @@
String getPackageName();
/** Path of base APK */
- String getBaseCodePath();
+ String getBaseApkPath();
/**
* Path where this package was found on disk. For monolithic packages
@@ -556,7 +556,7 @@
* path to the cluster directory.
*/
@NonNull
- String getCodePath();
+ String getPath();
/**
* @see ApplicationInfo#compatibleWidthLimitDp
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index d9857e0..bce75cd 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -127,7 +127,7 @@
*/
public class ParsingPackageUtils {
- public static final String TAG = ParsingUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
/**
* @see #parseDefault(ParseInput, File, int, boolean)
@@ -162,10 +162,10 @@
@Override
public ParsingPackage startParsingPackage(
@NonNull String packageName,
- @NonNull String baseCodePath,
- @NonNull String codePath,
+ @NonNull String baseApkPath,
+ @NonNull String path,
@NonNull TypedArray manifestArray, boolean isCoreApp) {
- return new ParsingPackageImpl(packageName, baseCodePath, codePath, manifestArray);
+ return new ParsingPackageImpl(packageName, baseApkPath, path, manifestArray);
}
});
try {
@@ -739,7 +739,6 @@
String tagName = parser.getName();
final ParseResult result;
- // TODO(b/135203078): Convert to instance methods to share variables
// <application> has special logic, so it's handled outside the general method
if (PackageParser.TAG_APPLICATION.equals(tagName)) {
if (foundApp) {
@@ -1214,9 +1213,9 @@
features = ArrayUtils.add(features, featureInfo);
} else {
Slog.w(TAG,
- "Unknown element under <feature-group>: " + innerTagName +
- " at " + pkg.getBaseCodePath() + " " +
- parser.getPositionDescription());
+ "Unknown element under <feature-group>: " + innerTagName
+ + " at " + pkg.getBaseApkPath() + " "
+ + parser.getPositionDescription());
}
}
@@ -1719,10 +1718,6 @@
pkg.setPersistent(requiredFeature == null || mCallback.hasFeature(requiredFeature));
}
- // TODO(b/135203078): Should parsing code be responsible for this? Maybe move to a
- // util or just have PackageImpl return true if either flag is set
- pkg.setProfileableByShell(pkg.isProfileableByShell());
-
if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
pkg.setResizeableActivity(sa.getBoolean(
R.styleable.AndroidManifestApplication_resizeableActivity, true));
@@ -2424,7 +2419,7 @@
R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
if (!PackageParser.checkRequiredSystemProperties(propName, propValue)) {
String message = "Skipping target and overlay pair " + target + " and "
- + pkg.getBaseCodePath()
+ + pkg.getBaseApkPath()
+ ": overlay ignored due to required system property: "
+ propName + " with value: " + propValue;
Slog.i(TAG, message);
@@ -2679,7 +2674,7 @@
"<meta-data> only supports string, integer, float, color, "
+ "boolean, and resource reference types: "
+ parser.getName() + " at "
- + pkg.getBaseCodePath() + " "
+ + pkg.getBaseApkPath() + " "
+ parser.getPositionDescription());
} else {
return input.error("<meta-data> only supports string, integer, float, "
@@ -2716,7 +2711,7 @@
try {
ParseResult<SigningDetails> result = getSigningDetails(
input,
- pkg.getBaseCodePath(),
+ pkg.getBaseApkPath(),
skipVerify,
pkg.isStaticSharedLibrary(),
signingDetails,
@@ -2862,7 +2857,7 @@
boolean hasFeature(String feature);
ParsingPackage startParsingPackage(@NonNull String packageName,
- @NonNull String baseCodePath, @NonNull String codePath,
+ @NonNull String baseApkPath, @NonNull String path,
@NonNull TypedArray manifestArray, boolean isCoreApp);
}
}
diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java
index ba61de1..5da5fbf 100644
--- a/core/java/android/content/pm/parsing/ParsingUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingUtils.java
@@ -33,7 +33,6 @@
/** @hide **/
public class ParsingUtils {
- // TODO(b/135203078): Consolidate log tags
public static final String TAG = "PackageParsing";
@Nullable
@@ -62,7 +61,7 @@
return input.error("Bad element under " + parentTag + ": " + parser.getName());
}
Slog.w(TAG, "Unknown element under " + parentTag + ": "
- + parser.getName() + " at " + pkg.getBaseCodePath() + " "
+ + parser.getName() + " at " + pkg.getBaseApkPath() + " "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
return input.success(null); // Type doesn't matter
diff --git a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
index c4caedc..cfefc016 100644
--- a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
@@ -24,15 +24,13 @@
import android.content.pm.PackageUserState;
import android.content.pm.parsing.ParsingPackage;
import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.text.TextUtils;
-import android.content.pm.parsing.ParsingPackageUtils;
-import android.content.pm.parsing.result.ParseInput;
-import android.content.pm.parsing.result.ParseResult;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -41,8 +39,6 @@
/** @hide */
public class ComponentParseUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
-
public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) {
return intentInfo.hasCategory(Intent.CATEGORY_BROWSABLE)
|| intentInfo.hasAction(Intent.ACTION_SEND)
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
index 6927f3b..8c0bfef 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -24,7 +24,6 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageParser;
import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseInput.DeferredError;
@@ -55,7 +54,7 @@
/** @hide */
public class ParsedActivityUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
index 6811e06..dd2fb5b 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
@@ -36,8 +36,6 @@
/** @hide */
class ParsedComponentUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
-
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
static <Component extends ParsedComponent> ParseResult<Component> parseComponent(
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
index 0ba92cc..6b797bc 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -22,7 +22,6 @@
import android.os.Parcelable;
import android.util.Pair;
-import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
import java.util.ArrayList;
@@ -163,7 +162,7 @@
}
public String toString() {
- return "ProviderIntentInfo{"
+ return "ParsedIntentInfo{"
+ Integer.toHexString(System.identityHashCode(this))
+ '}';
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
index 390f769..c0536bb 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
@@ -21,7 +21,6 @@
import android.content.IntentFilter;
import android.content.pm.PackageParser;
import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
@@ -43,7 +42,7 @@
/** @hide */
public class ParsedIntentInfoUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
@NonNull
public static ParseResult<ParsedIntentInfo> parseIntentInfo(String className,
diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
index f4c9914..f70d62b 100644
--- a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.content.IntentFilter;
import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.res.Configuration;
@@ -39,7 +39,7 @@
/** @hide */
class ParsedMainComponentUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -113,7 +113,7 @@
ParsedIntentInfo intent = intentResult.getResult();
int actionCount = intent.countActions();
if (actionCount == 0 && failOnNoActions) {
- Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseCodePath() + " "
+ Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseApkPath() + " "
+ parser.getPositionDescription());
// Backward-compat, do not actually fail
return input.success(null);
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
index 1884a1e..894849a 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
@@ -19,15 +19,15 @@
import android.annotation.NonNull;
import android.content.pm.PermissionInfo;
import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.Slog;
import com.android.internal.R;
-import android.content.pm.parsing.ParsingPackageUtils;
-import android.content.pm.parsing.result.ParseInput;
-import android.content.pm.parsing.result.ParseResult;
import org.xmlpull.v1.XmlPullParserException;
@@ -36,7 +36,7 @@
/** @hide */
public class ParsedPermissionUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
@NonNull
public static ParseResult<ParsedPermission> parsePermission(ParsingPackage pkg, Resources res,
@@ -106,11 +106,6 @@
sa.recycle();
}
- // TODO(b/135203078): This is impossible because of default value in above getInt
- if (permission.protectionLevel == -1) {
- return input.error("<permission> does not specify protectionLevel");
- }
-
permission.protectionLevel = PermissionInfo.fixProtectionLevel(permission.protectionLevel);
if (permission.getProtectionFlags() != 0) {
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
index 8372707..9bff719 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
@@ -40,8 +40,6 @@
/** @hide */
public class ParsedProcessUtils {
- private static final String TAG = ParsingUtils.TAG;
-
@NonNull
private static ParseResult<Set<String>> parseDenyPermission(Set<String> perms,
Resources res, XmlResourceParser parser, ParseInput input)
diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
index aa5ea8d..37cbeca 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
@@ -23,7 +23,6 @@
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
@@ -45,7 +44,7 @@
/** @hide */
public class ParsedProviderUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
+ private static final String TAG = ParsingUtils.TAG;
@NonNull
public static ParseResult<ParsedProvider> parseProvider(String[] separateProcesses,
@@ -247,7 +246,7 @@
}
Slog.w(TAG, "Unknown element under <path-permission>: " + name + " at "
- + pkg.getBaseCodePath() + " " + parser.getPositionDescription());
+ + pkg.getBaseApkPath() + " " + parser.getPositionDescription());
}
return input.success(provider);
@@ -293,7 +292,8 @@
"No readPermission or writePermission for <path-permission>");
}
Slog.w(TAG, "No readPermission or writePermission for <path-permission>: "
- + name + " at " + pkg.getBaseCodePath() + " " + parser.getPositionDescription());
+ + name + " at " + pkg.getBaseApkPath() + " "
+ + parser.getPositionDescription());
return input.success(provider);
}
@@ -342,7 +342,7 @@
}
Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
- + name + " at " + pkg.getBaseCodePath()
+ + name + " at " + pkg.getBaseApkPath()
+ " "
+ parser.getPositionDescription());
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
index a8d2d67..afe3c54 100644
--- a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
@@ -22,7 +22,6 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseInput.DeferredError;
@@ -43,8 +42,6 @@
/** @hide */
public class ParsedServiceUtils {
- private static final String TAG = ParsingPackageUtils.TAG;
-
@NonNull
public static ParseResult<ParsedService> parseService(String[] separateProcesses,
ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags,
diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
index 14992fb..0f90b53 100644
--- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
+++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
@@ -95,7 +95,7 @@
return platformCompat.isChangeEnabled(changeId, appInfo);
} catch (Exception e) {
// This shouldn't happen, but assume enforcement if it does
- Slog.wtf(ParsingUtils.TAG, "IPlatformCompat query failed", e);
+ Slog.wtf(TAG, "IPlatformCompat query failed", e);
return true;
}
});
@@ -125,7 +125,7 @@
@Override
public <ResultType> ParseResult<ResultType> success(ResultType result) {
if (mErrorCode != PackageManager.INSTALL_SUCCEEDED) {
- Slog.wtf(ParsingUtils.TAG, "Cannot set to success after set to error, was "
+ Slog.wtf(TAG, "Cannot set to success after set to error, was "
+ mErrorMessage, mException);
}
mResult = result;
diff --git a/core/java/android/hardware/face/FaceSensorProperties.java b/core/java/android/hardware/face/FaceSensorProperties.java
index 1015724..23ad935 100644
--- a/core/java/android/hardware/face/FaceSensorProperties.java
+++ b/core/java/android/hardware/face/FaceSensorProperties.java
@@ -40,21 +40,27 @@
* from above the HAL.
*/
public final boolean supportsSelfIllumination;
+ /**
+ * Maximum number of enrollments a user/profile can have.
+ */
+ public final int maxTemplatesAllowed;
/**
* Initializes SensorProperties with specified values
*/
public FaceSensorProperties(int sensorId, boolean supportsFaceDetection,
- boolean supportsSelfIllumination) {
+ boolean supportsSelfIllumination, int maxTemplatesAllowed) {
this.sensorId = sensorId;
this.supportsFaceDetection = supportsFaceDetection;
this.supportsSelfIllumination = supportsSelfIllumination;
+ this.maxTemplatesAllowed = maxTemplatesAllowed;
}
protected FaceSensorProperties(Parcel in) {
sensorId = in.readInt();
supportsFaceDetection = in.readBoolean();
supportsSelfIllumination = in.readBoolean();
+ maxTemplatesAllowed = in.readInt();
}
public static final Creator<FaceSensorProperties> CREATOR =
@@ -80,5 +86,6 @@
dest.writeInt(sensorId);
dest.writeBoolean(supportsFaceDetection);
dest.writeBoolean(supportsSelfIllumination);
+ dest.writeInt(maxTemplatesAllowed);
}
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
index b28551c..2fd0068 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
@@ -48,21 +48,25 @@
// IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT
// cannot be checked
public final boolean resetLockoutRequiresHardwareAuthToken;
+ // Maximum number of enrollments a user/profile can have.
+ public final int maxTemplatesAllowed;
/**
* Initializes SensorProperties with specified values
*/
public FingerprintSensorProperties(int sensorId, @SensorType int sensorType,
- boolean resetLockoutRequiresHardwareAuthToken) {
+ boolean resetLockoutRequiresHardwareAuthToken, int maxTemplatesAllowed) {
this.sensorId = sensorId;
this.sensorType = sensorType;
this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken;
+ this.maxTemplatesAllowed = maxTemplatesAllowed;
}
protected FingerprintSensorProperties(Parcel in) {
sensorId = in.readInt();
sensorType = in.readInt();
resetLockoutRequiresHardwareAuthToken = in.readBoolean();
+ maxTemplatesAllowed = in.readInt();
}
public static final Creator<FingerprintSensorProperties> CREATOR =
@@ -88,5 +92,6 @@
dest.writeInt(sensorId);
dest.writeInt(sensorType);
dest.writeBoolean(resetLockoutRequiresHardwareAuthToken);
+ dest.writeInt(maxTemplatesAllowed);
}
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 8e865e7..1db544c 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1027,6 +1027,18 @@
/**
* R.
+ *
+ * <p>Applications targeting this or a later release will get these new changes in behavior.
+ * For more information about this release, see the
+ * <a href="/about/versions/11">Android 11 overview</a>.</p>
+ * <ul>
+ * <li><a href="/about/versions/11/behavior-changes-all">Behavior changes: all apps</a></li>
+ * <li><a href="/about/versions/11/behavior-changes-11">Behavior changes: Apps targeting
+ * Android 11</a></li>
+ * <li><a href="/about/versions/11/non-sdk-11">Updates to non-SDK interface restrictions
+ * in Android 11</a></li>
+ * </ul>
+ *
*/
public static final int R = 30;
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index e05991b..a79a1cf 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -118,7 +118,7 @@
* affects them.
*/
public abstract void onAppOpsChanged(int code, int uid,
- @Nullable String packageName, int mode);
+ @Nullable String packageName, int mode, int previousMode);
/**
* Asks the StorageManager to reset all state for the provided user; this will result
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 739e169..18337b6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6801,6 +6801,13 @@
public static final String KEYGUARD_SLICE_URI = "keyguard_slice_uri";
/**
+ * Whether to draw text in bold.
+ *
+ * @hide
+ */
+ public static final String FORCE_BOLD_TEXT = "force_bold_text";
+
+ /**
* Whether to speak passwords while in accessibility mode.
*
* @deprecated The speaking of passwords is controlled by individual accessibility services.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e083417..19860eb 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -71,6 +71,7 @@
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.window.ClientWindowFrames;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.HandlerCaller;
@@ -186,17 +187,11 @@
int mCurWindowFlags = mWindowFlags;
int mCurWindowPrivateFlags = mWindowPrivateFlags;
Rect mPreviewSurfacePosition;
- final Rect mVisibleInsets = new Rect();
- final Rect mWinFrame = new Rect();
- final Rect mContentInsets = new Rect();
- final Rect mStableInsets = new Rect();
+ final ClientWindowFrames mWinFrames = new ClientWindowFrames();
final Rect mDispatchedContentInsets = new Rect();
final Rect mDispatchedStableInsets = new Rect();
final Rect mFinalSystemInsets = new Rect();
final Rect mFinalStableInsets = new Rect();
- final Rect mBackdropFrame = new Rect();
- final DisplayCutout.ParcelableWrapper mDisplayCutout =
- new DisplayCutout.ParcelableWrapper();
DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT;
final InsetsState mInsetsState = new InsetsState();
final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
@@ -332,11 +327,9 @@
final BaseIWindow mWindow = new BaseIWindow() {
@Override
- public void resized(Rect frame, Rect contentInsets,
- Rect visibleInsets, Rect stableInsets, boolean reportDraw,
- MergedConfiguration mergedConfiguration, Rect backDropRect, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0);
mCaller.sendMessage(msg);
@@ -749,10 +742,7 @@
out.print(" mCurWindowFlags="); out.println(mCurWindowFlags);
out.print(prefix); out.print("mWindowPrivateFlags="); out.print(mWindowPrivateFlags);
out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags);
- out.print(prefix); out.print("mVisibleInsets=");
- out.print(mVisibleInsets.toShortString());
- out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
- out.print(" mContentInsets="); out.println(mContentInsets.toShortString());
+ out.print(prefix); out.println("mWinFrames="); out.println(mWinFrames);
out.print(prefix); out.print("mConfiguration=");
out.println(mMergedConfiguration.getMergedConfiguration());
out.print(prefix); out.print("mLayout="); out.println(mLayout);
@@ -890,8 +880,8 @@
InputChannel inputChannel = new InputChannel();
if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
- mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets,
- mDisplayCutout, inputChannel,
+ mDisplay.getDisplayId(), mWinFrames.frame, mWinFrames.contentInsets,
+ mWinFrames.stableInsets, mWinFrames.displayCutout, inputChannel,
mInsetsState, mTempControls) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
@@ -914,34 +904,32 @@
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
- View.VISIBLE, 0, -1, mWinFrame, mContentInsets,
- mVisibleInsets, mStableInsets, mBackdropFrame,
- mDisplayCutout, mMergedConfiguration, mSurfaceControl,
+ View.VISIBLE, 0, -1, mWinFrames, mMergedConfiguration, mSurfaceControl,
mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl);
if (mSurfaceControl.isValid()) {
mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
}
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
- + ", frame=" + mWinFrame);
+ + ", frame=" + mWinFrames);
- int w = mWinFrame.width();
- int h = mWinFrame.height();
+ int w = mWinFrames.frame.width();
+ int h = mWinFrames.frame.height();
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
w += padding.left + padding.right;
h += padding.top + padding.bottom;
- mContentInsets.left += padding.left;
- mContentInsets.top += padding.top;
- mContentInsets.right += padding.right;
- mContentInsets.bottom += padding.bottom;
- mStableInsets.left += padding.left;
- mStableInsets.top += padding.top;
- mStableInsets.right += padding.right;
- mStableInsets.bottom += padding.bottom;
- mDisplayCutout.set(mDisplayCutout.get().inset(-padding.left, -padding.top,
- -padding.right, -padding.bottom));
+ mWinFrames.contentInsets.left += padding.left;
+ mWinFrames.contentInsets.top += padding.top;
+ mWinFrames.contentInsets.right += padding.right;
+ mWinFrames.contentInsets.bottom += padding.bottom;
+ mWinFrames.stableInsets.left += padding.left;
+ mWinFrames.stableInsets.top += padding.top;
+ mWinFrames.stableInsets.right += padding.right;
+ mWinFrames.stableInsets.bottom += padding.bottom;
+ mWinFrames.displayCutout.set(mWinFrames.displayCutout.get().inset(
+ -padding.left, -padding.top, -padding.right, -padding.bottom));
} else {
w = myWidth;
h = myHeight;
@@ -960,9 +948,10 @@
Log.v(TAG, "Wallpaper size has changed: (" + mCurWidth + ", " + mCurHeight);
}
- insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets);
- insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets);
- insetsChanged |= !mDispatchedDisplayCutout.equals(mDisplayCutout.get());
+ final DisplayCutout displayCutout = mWinFrames.displayCutout.get();
+ insetsChanged |= !mDispatchedContentInsets.equals(mWinFrames.contentInsets);
+ insetsChanged |= !mDispatchedStableInsets.equals(mWinFrames.stableInsets);
+ insetsChanged |= !mDispatchedDisplayCutout.equals(displayCutout);
mSurfaceHolder.setSurfaceFrameSize(w, h);
mSurfaceHolder.mSurfaceLock.unlock();
@@ -1021,9 +1010,9 @@
}
if (insetsChanged) {
- mDispatchedContentInsets.set(mContentInsets);
- mDispatchedStableInsets.set(mStableInsets);
- mDispatchedDisplayCutout = mDisplayCutout.get();
+ mDispatchedContentInsets.set(mWinFrames.contentInsets);
+ mDispatchedStableInsets.set(mWinFrames.stableInsets);
+ mDispatchedDisplayCutout = displayCutout;
mFinalStableInsets.set(mDispatchedStableInsets);
WindowInsets insets = new WindowInsets(mFinalSystemInsets,
mFinalStableInsets,
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 4b42209..5fd192a 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -183,10 +183,9 @@
@NonNull String packageName, @Nullable String featureId) {
if (DBG) Log.d(TAG, "checkPermissions");
if (forDataDelivery) {
- if (PermissionChecker.checkCallingPermissionForDataDelivery(this,
+ if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this,
android.Manifest.permission.RECORD_AUDIO, packageName, featureId,
- null /*message*/)
- == PermissionChecker.PERMISSION_GRANTED) {
+ null /*message*/) == PermissionChecker.PERMISSION_GRANTED) {
return true;
}
} else {
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index e338fd97..0973608 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -65,6 +65,7 @@
DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true");
DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
+ DEFAULT_FLAGS.put("settings_silky_home", "false");
}
/**
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index e09bf9d..94e641c 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -29,6 +29,7 @@
import android.view.IScrollCaptureController;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.window.ClientWindowFrames;
import com.android.internal.os.IResultReceiver;
@@ -52,11 +53,9 @@
*/
void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
- void resized(in Rect frame, in Rect contentInsets,
- in Rect visibleInsets, in Rect stableInsets, boolean reportDraw,
- in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
- boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
- in DisplayCutout.ParcelableWrapper displayCutout);
+ void resized(in ClientWindowFrames frames, boolean reportDraw,
+ in MergedConfiguration newMergedConfiguration,
+ boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
/**
* Called when the window location in parent display has changed. The offset will only be a
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 00fc672..8e875d7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -393,11 +393,6 @@
oneway void setRecentsVisibility(boolean visible);
/**
- * Called by System UI to notify of changes to the visibility of PIP.
- */
- oneway void setPipVisibility(boolean visible);
-
- /**
* Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
*/
@UnsupportedAppUsage
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 819e89b..70850d8 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -34,6 +34,7 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.window.ClientWindowFrames;
import java.util.List;
@@ -107,10 +108,7 @@
*/
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
- int flags, long frameNumber, out Rect outFrame,
- out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
- out Rect outBackdropFrame,
- out DisplayCutout.ParcelableWrapper displayCutout,
+ int flags, long frameNumber, out ClientWindowFrames outFrames,
out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
out InsetsState insetsState, out InsetsSourceControl[] activeControls,
out Point outSurfaceSize, out SurfaceControl outBlastSurfaceControl);
@@ -152,12 +150,6 @@
in Rect visibleInsets, in Region touchableRegion);
/**
- * Return the current display size in which the window is being laid out,
- * accounting for screen decorations around it.
- */
- void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
-
- /**
* Called when the client has finished drawing the surface, if needed.
*
* @param postDrawTransaction transaction filled by the client that can be
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index e249c77..0ab1751 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1908,8 +1908,6 @@
/**
* Returns whether this key will be sent to the
* {@link android.media.session.MediaSession.Callback} if not handled.
- *
- * @hide
*/
public static final boolean isMediaSessionKey(int keyCode) {
switch (keyCode) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3af8958..2bd3c06 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -65,9 +65,6 @@
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
/**
* Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -90,10 +87,10 @@
private static native void nativeWriteToParcel(long nativeObject, Parcel out);
private static native void nativeRelease(long nativeObject);
private static native void nativeDisconnect(long nativeObject);
- private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
- ScreenCaptureListener captureListener);
- private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
- ScreenCaptureListener captureListener);
+ private static native ScreenshotHardwareBuffer nativeCaptureDisplay(
+ DisplayCaptureArgs captureArgs);
+ private static native ScreenshotHardwareBuffer nativeCaptureLayers(
+ LayerCaptureArgs captureArgs);
private static native long nativeMirrorSurface(long mirrorOfObject);
private static native long nativeCreateTransaction();
private static native long nativeGetNativeTransactionFinalizer();
@@ -224,6 +221,8 @@
private static native void nativeReleaseFrameRateFlexibilityToken(long token);
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
int transformHint);
+ private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken,
+ IBinder focusedToken, int displayId);
@Nullable
@GuardedBy("mLock")
@@ -496,8 +495,6 @@
private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696;
private static final int INTERNAL_DATASPACE_SCRGB = 411107328;
- private static final int SCREENSHOT_WAIT_TIME_S = 1;
-
private void assignNativeObject(long nativeObject, String callsite) {
if (mNativeObject != 0) {
release();
@@ -616,13 +613,6 @@
}
/**
- * @hide
- */
- public abstract static class ScreenCaptureListener {
- abstract void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer);
- }
-
- /**
* A common arguments class used for various screenshot requests. This contains arguments that
* are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
* @hide
@@ -697,7 +687,7 @@
/**
* The arguments class used to make display capture requests.
*
- * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener)
+ * @see #nativeCaptureDisplay(DisplayCaptureArgs)
* @hide
*/
public static class DisplayCaptureArgs extends CaptureArgs {
@@ -2238,46 +2228,13 @@
}
/**
- * @param captureArgs Arguments about how to take the screenshot
- * @param captureListener A listener to receive the screenshot callback
- * @hide
- */
- public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
- @NonNull ScreenCaptureListener captureListener) {
- return nativeCaptureDisplay(captureArgs, captureListener);
- }
-
- /**
* Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
* the content.
*
* @hide
*/
public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
- final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer =
- new AtomicReference<>(null);
-
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() {
- @Override
- void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) {
- outHardwareBuffer.set(hardwareBuffer);
- countDownLatch.countDown();
- }
- };
-
- int status = captureDisplay(captureArgs, screenCaptureListener);
- if (status != 0) {
- return null;
- }
-
- try {
- countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
- } catch (Exception e) {
- Log.e(TAG, "Failed to wait for captureDisplay result", e);
- }
-
- return outHardwareBuffer.get();
+ return nativeCaptureDisplay(captureArgs);
}
/**
@@ -2322,37 +2279,14 @@
.setPixelFormat(format)
.build();
- return captureLayers(captureArgs);
+ return nativeCaptureLayers(captureArgs);
}
/**
* @hide
*/
public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) {
- final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer =
- new AtomicReference<>(null);
-
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() {
- @Override
- void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) {
- outHardwareBuffer.set(hardwareBuffer);
- countDownLatch.countDown();
- }
- };
-
- int status = captureLayers(captureArgs, screenCaptureListener);
- if (status != 0) {
- return null;
- }
-
- try {
- countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
- } catch (Exception e) {
- Log.e(TAG, "Failed to wait for captureLayers result", e);
- }
-
- return outHardwareBuffer.get();
+ return nativeCaptureLayers(captureArgs);
}
/**
@@ -2369,17 +2303,7 @@
.setExcludeLayers(exclude)
.build();
- return captureLayers(captureArgs);
- }
-
- /**
- * @param captureArgs Arguments about how to take the screenshot
- * @param captureListener A listener to receive the screenshot callback
- * @hide
- */
- public static int captureLayers(@NonNull LayerCaptureArgs captureArgs,
- @NonNull ScreenCaptureListener captureListener) {
- return nativeCaptureLayers(captureArgs, captureListener);
+ return nativeCaptureLayers(captureArgs);
}
/**
@@ -3262,6 +3186,39 @@
}
/**
+ * Sets focus on the window identified by the input {@code token} if the window is focusable
+ * otherwise the request is dropped.
+ *
+ * If the window is not visible, the request will be queued until the window becomes
+ * visible or the request is overrriden by another request. The currently focused window
+ * will lose focus immediately. This is to send the newly focused window any focus
+ * dispatched events that occur while it is completing its first draw.
+ *
+ * @hide
+ */
+ public Transaction setFocusedWindow(@NonNull IBinder token, int displayId) {
+ nativeSetFocusedWindow(mNativeObject, token, null /* focusedToken */, displayId);
+ return this;
+ }
+
+ /**
+ * Set focus on the window identified by the input {@code token} if the window identified by
+ * the input {@code focusedToken} is currently focused. If the {@code focusedToken} does not
+ * have focus, the request is dropped.
+ *
+ * This is used by forward focus transfer requests from clients that host embedded windows,
+ * and want to transfer focus to/from them.
+ *
+ * @hide
+ */
+ public Transaction requestFocusTransfer(@NonNull IBinder token,
+ @NonNull IBinder focusedToken,
+ int displayId) {
+ nativeSetFocusedWindow(mNativeObject, token, focusedToken, displayId);
+ return this;
+ }
+
+ /**
* Merge the other transaction into this transaction, clearing the
* other transaction as if it had been applied.
*
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8917821..92a0f63 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14940,20 +14940,12 @@
* inside. In effect, this tells you the available area where content can
* be placed and remain visible to users.
*
- * <p>This function requires an IPC back to the window manager to retrieve
- * the requested information, so should not be used in performance critical
- * code like drawing.
- *
* @param outRect Filled in with the visible display frame. If the view
* is not attached to a window, this is simply the raw display size.
*/
public void getWindowVisibleDisplayFrame(Rect outRect) {
if (mAttachInfo != null) {
- try {
- mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
- } catch (RemoteException e) {
- return;
- }
+ mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
// XXX This is really broken, and probably all needs to be done
// in the window manager, and we need to know more about whether
// we want the area behind or in front of the IME.
@@ -14979,11 +14971,7 @@
@UnsupportedAppUsage
public void getWindowDisplayFrame(Rect outRect) {
if (mAttachInfo != null) {
- try {
- mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
- } catch (RemoteException e) {
- return;
- }
+ mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
return;
}
// The view is not attached to a display so we don't have a context.
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 8a5be75..4303d70 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -33,7 +33,6 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -755,11 +754,7 @@
try {
Rect outRect = new Rect();
- try {
- root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect);
- } catch (RemoteException e) {
- // Ignore
- }
+ root.mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
clientStream.writeInt(outRect.width());
clientStream.writeInt(outRect.height());
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f3a8d97..af839d4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -137,7 +137,6 @@
import android.view.Window.OnContentApplyWindowInsetsListener;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -160,6 +159,7 @@
import android.view.contentcapture.MainContentCaptureSession;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
+import android.window.ClientWindowFrames;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -465,6 +465,7 @@
// used in relayout to get SurfaceControl size
// for BLAST adapter surface setup
private final Point mSurfaceSize = new Point();
+ private final Point mLastSurfaceSize = new Point();
final Rect mTempRect; // used in the transaction to not thrash the heap.
final Rect mVisRect; // used to retrieve visible rect of focused view.
@@ -559,8 +560,11 @@
boolean mAdded;
boolean mAddedTouchMode;
- final Rect mTmpFrame = new Rect();
- final Rect mTmpRect = new Rect();
+ /**
+ * It usually keeps the latest layout result from {@link IWindow#resized} or
+ * {@link IWindowSession#relayout}.
+ */
+ private final ClientWindowFrames mTmpFrames = new ClientWindowFrames();
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -1032,11 +1036,11 @@
collectViewAttributes();
adjustLayoutParamsForCompatibility(mWindowAttributes);
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
+ getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrames.frame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
- setFrame(mTmpFrame);
+ setFrame(mTmpFrames.frame);
} catch (RemoteException e) {
mAdded = false;
mView = null;
@@ -1474,6 +1478,55 @@
scheduleTraversals();
}
+ /** Handles messages {@link #MSG_RESIZED} and {@link #MSG_RESIZED_REPORT}. */
+ private void handleResized(int msg, SomeArgs args) {
+ if (!mAdded) {
+ return;
+ }
+
+ final ClientWindowFrames frames = (ClientWindowFrames) args.arg1;
+ final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg2;
+ final boolean forceNextWindowRelayout = args.argi1 != 0;
+ final int displayId = args.argi3;
+ final Rect backdropFrame = frames.backdropFrame;
+ final DisplayCutout displayCutout = frames.displayCutout.get();
+
+ final boolean frameChanged = !mWinFrame.equals(frames.frame);
+ final boolean cutoutChanged = !mPendingDisplayCutout.get().equals(displayCutout);
+ final boolean backdropFrameChanged = !mPendingBackDropFrame.equals(backdropFrame);
+ final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration);
+ final boolean displayChanged = mDisplay.getDisplayId() != displayId;
+ if (msg == MSG_RESIZED && !frameChanged && !cutoutChanged && !backdropFrameChanged
+ && !configChanged && !displayChanged && !forceNextWindowRelayout) {
+ return;
+ }
+
+ if (configChanged) {
+ // If configuration changed - notify about that and, maybe, about move to display.
+ performConfigurationChange(mergedConfiguration, false /* force */,
+ displayChanged ? displayId : INVALID_DISPLAY /* same display */);
+ } else if (displayChanged) {
+ // Moved to display without config change - report last applied one.
+ onMovedToDisplay(displayId, mLastConfigurationFromResources);
+ }
+
+ setFrame(frames.frame);
+ mTmpFrames.displayFrame.set(frames.displayFrame);
+ mPendingDisplayCutout.set(displayCutout);
+ mPendingBackDropFrame.set(backdropFrame);
+ mForceNextWindowRelayout = forceNextWindowRelayout;
+ mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
+
+ if (msg == MSG_RESIZED_REPORT) {
+ reportNextDraw();
+ }
+
+ if (mView != null && (frameChanged || cutoutChanged || configChanged)) {
+ forceLayout(mView);
+ }
+ requestLayout();
+ }
+
private final DisplayListener mDisplayListener = new DisplayListener() {
@Override
public void onDisplayChanged(int displayId) {
@@ -2641,9 +2694,12 @@
}
cutoutChanged = !mPendingDisplayCutout.equals(mAttachInfo.mDisplayCutout);
- surfaceSizeChanged = (relayoutResult
- & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
- final boolean alwaysConsumeSystemBarsChanged =
+ surfaceSizeChanged = false;
+ if (!mLastSurfaceSize.equals(mSurfaceSize)) {
+ surfaceSizeChanged = true;
+ mLastSurfaceSize.set(mSurfaceSize.x, mSurfaceSize.y);
+ }
+ final boolean alwaysConsumeSystemBarsChanged =
mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
updateColorModeIfNeeded(lp.getColorMode());
surfaceCreated = !hadSurface && mSurface.isValid();
@@ -4919,60 +4975,13 @@
case MSG_DISPATCH_GET_NEW_SURFACE:
handleGetNewSurface();
break;
- case MSG_RESIZED: {
- // Recycled in the fall through...
- SomeArgs args = (SomeArgs) msg.obj;
- if (mWinFrame.equals(args.arg1)
- && mPendingDisplayCutout.get().equals(args.arg9)
- && mPendingBackDropFrame.equals(args.arg8)
- && mLastReportedMergedConfiguration.equals(args.arg4)
- && args.argi1 == 0
- && mDisplay.getDisplayId() == args.argi3) {
- break;
- }
- } // fall through...
- case MSG_RESIZED_REPORT:
- if (mAdded) {
- SomeArgs args = (SomeArgs) msg.obj;
-
- final int displayId = args.argi3;
- MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
- final boolean displayChanged = mDisplay.getDisplayId() != displayId;
- boolean configChanged = false;
-
- if (!mLastReportedMergedConfiguration.equals(mergedConfiguration)) {
- // If configuration changed - notify about that and, maybe,
- // about move to display.
- performConfigurationChange(mergedConfiguration, false /* force */,
- displayChanged
- ? displayId : INVALID_DISPLAY /* same display */);
- configChanged = true;
- } else if (displayChanged) {
- // Moved to display without config change - report last applied one.
- onMovedToDisplay(displayId, mLastConfigurationFromResources);
- }
-
- final boolean framesChanged = !mWinFrame.equals(args.arg1)
- || !mPendingDisplayCutout.get().equals(args.arg9);
-
- setFrame((Rect) args.arg1);
- mPendingDisplayCutout.set((DisplayCutout) args.arg9);
- mPendingBackDropFrame.set((Rect) args.arg8);
- mForceNextWindowRelayout = args.argi1 != 0;
- mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
-
- args.recycle();
-
- if (msg.what == MSG_RESIZED_REPORT) {
- reportNextDraw();
- }
-
- if (mView != null && (framesChanged || configChanged)) {
- forceLayout(mView);
- }
- requestLayout();
- }
+ case MSG_RESIZED:
+ case MSG_RESIZED_REPORT: {
+ final SomeArgs args = (SomeArgs) msg.obj;
+ handleResized(msg.what, args);
+ args.recycle();
break;
+ }
case MSG_INSETS_CHANGED:
mInsetsController.onStateChanged((InsetsState) msg.obj);
break;
@@ -5007,11 +5016,11 @@
final int h = mWinFrame.height();
final int l = msg.arg1;
final int t = msg.arg2;
- mTmpFrame.left = l;
- mTmpFrame.right = l + w;
- mTmpFrame.top = t;
- mTmpFrame.bottom = t + h;
- setFrame(mTmpFrame);
+ mTmpFrames.frame.left = l;
+ mTmpFrames.frame.right = l + w;
+ mTmpFrames.frame.top = t;
+ mTmpFrames.frame.bottom = t + h;
+ setFrame(mTmpFrames.frame);
mPendingBackDropFrame.set(mWinFrame);
maybeHandleWindowMove(mWinFrame);
@@ -7418,9 +7427,10 @@
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
- mTmpFrame, mTmpRect, mTmpRect, mTmpRect, mPendingBackDropFrame,
- mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
+ mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
mTempControls, mSurfaceSize, mBlastSurfaceControl);
+ mPendingDisplayCutout.set(mTmpFrames.displayCutout);
+ mPendingBackDropFrame.set(mTmpFrames.backdropFrame);
if (mSurfaceControl.isValid()) {
if (!useBLAST()) {
mSurface.copyFrom(mSurfaceControl);
@@ -7446,9 +7456,9 @@
}
if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWinFrame(mTmpFrame);
+ mTranslator.translateRectInScreenToAppWinFrame(mTmpFrames.frame);
}
- setFrame(mTmpFrame);
+ setFrame(mTmpFrames.frame);
mInsetsController.onStateChanged(mTempInsets);
mInsetsController.onControlsChanged(mTempControls);
return relayoutResult;
@@ -7460,6 +7470,14 @@
}
/**
+ * Gets the current display size in which the window is being laid out, accounting for screen
+ * decorations around it.
+ */
+ void getDisplayFrame(Rect outFrame) {
+ outFrame.set(mTmpFrames.displayFrame);
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -7742,11 +7760,14 @@
}
@UnsupportedAppUsage
- private void dispatchResized(Rect frame, Rect contentInsets,
- Rect visibleInsets, Rect stableInsets, boolean reportDraw,
- MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
+ final Rect frame = frames.frame;
+ final Rect contentInsets = frames.contentInsets;
+ final Rect visibleInsets = frames.visibleInsets;
+ final Rect stableInsets = frames.stableInsets;
+ final Rect backDropFrame = frames.backdropFrame;
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
+ " contentInsets=" + contentInsets.toShortString()
+ " visibleInsets=" + visibleInsets.toShortString()
@@ -7773,14 +7794,9 @@
}
SomeArgs args = SomeArgs.obtain();
final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
- args.arg1 = sameProcessCall ? new Rect(frame) : frame;
- args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
- args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
- args.arg4 = sameProcessCall && mergedConfiguration != null
+ args.arg1 = sameProcessCall ? new ClientWindowFrames(frames) : frames;
+ args.arg2 = sameProcessCall && mergedConfiguration != null
? new MergedConfiguration(mergedConfiguration) : mergedConfiguration;
- args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
- args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
- args.arg9 = displayCutout.get(); // DisplayCutout is immutable.
args.argi1 = forceLayout ? 1 : 0;
args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
args.argi3 = displayId;
@@ -9074,17 +9090,13 @@
}
@Override
- public void resized(Rect frame, Rect contentInsets,
- Rect visibleInsets, Rect stableInsets, boolean reportDraw,
- MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchResized(frame, contentInsets,
- visibleInsets, stableInsets, reportDraw, mergedConfiguration,
- backDropFrame, forceLayout, alwaysConsumeSystemBars, displayId,
- displayCutout);
+ viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
+ alwaysConsumeSystemBars, displayId);
}
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 060311e..368918d 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -26,6 +26,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.MergedConfiguration;
+import android.window.ClientWindowFrames;
import java.util.HashMap;
import java.util.Objects;
@@ -224,9 +225,7 @@
@Override
public int relayout(IWindow window, int seq, WindowManager.LayoutParams inAttrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
- Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
- Rect outStableInsets, Rect outBackdropFrame,
- DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
+ ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
SurfaceControl outBLASTSurfaceControl) {
@@ -255,7 +254,8 @@
t.hide(sc).apply();
outSurfaceControl.release();
}
- outFrame.set(0, 0, attrs.width, attrs.height);
+ outFrames.frame.set(0, 0, attrs.width, attrs.height);
+ outFrames.displayFrame.set(outFrames.frame);
mergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
@@ -292,11 +292,6 @@
}
@Override
- public void getDisplayFrame(android.view.IWindow window,
- android.graphics.Rect outDisplayFrame) {
- }
-
- @Override
public void finishDrawing(android.view.IWindow window,
android.view.SurfaceControl.Transaction postDrawTransaction) {
synchronized (this) {
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/core/java/android/window/ClientWindowFrames.aidl
similarity index 61%
copy from packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
copy to core/java/android/window/ClientWindowFrames.aidl
index e65f19d..22bbea9 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
+++ b/core/java/android/window/ClientWindowFrames.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package com.android.keyguard.dagger;
+package android.window;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface ContainerView {
-}
+parcelable ClientWindowFrames;
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
new file mode 100644
index 0000000..0523e64
--- /dev/null
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2020 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.window;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.DisplayCutout;
+
+/**
+ * The window frame container class used by client side for layout.
+ * @hide
+ */
+public class ClientWindowFrames implements Parcelable {
+ /** The actual window bounds. */
+ public final @NonNull Rect frame;
+
+ /**
+ * The container frame that is usually the same as display size. It may exclude the area of
+ * insets if the window layout parameter has specified fit-insets-sides.
+ */
+ public final @NonNull Rect displayFrame;
+
+ /** The background area while the window is resizing. */
+ public final @NonNull Rect backdropFrame;
+
+ /** The area cut from the display. */
+ public final @NonNull DisplayCutout.ParcelableWrapper displayCutout;
+
+ // TODO(b/149813814): Remove legacy insets.
+ public final Rect contentInsets;
+ public final Rect visibleInsets;
+ public final Rect stableInsets;
+
+ public ClientWindowFrames() {
+ frame = new Rect();
+ displayFrame = new Rect();
+ backdropFrame = new Rect();
+ displayCutout = new DisplayCutout.ParcelableWrapper();
+ contentInsets = new Rect();
+ visibleInsets = new Rect();
+ stableInsets = new Rect();
+ }
+
+ public ClientWindowFrames(ClientWindowFrames other) {
+ frame = new Rect(other.frame);
+ displayFrame = new Rect(other.displayFrame);
+ backdropFrame = new Rect(other.backdropFrame);
+ displayCutout = new DisplayCutout.ParcelableWrapper(other.displayCutout.get());
+ contentInsets = new Rect(other.contentInsets);
+ visibleInsets = new Rect(other.visibleInsets);
+ stableInsets = new Rect(other.stableInsets);
+ }
+
+ private ClientWindowFrames(Parcel in) {
+ frame = Rect.CREATOR.createFromParcel(in);
+ displayFrame = Rect.CREATOR.createFromParcel(in);
+ backdropFrame = Rect.CREATOR.createFromParcel(in);
+ displayCutout = DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in);
+ contentInsets = Rect.CREATOR.createFromParcel(in);
+ visibleInsets = Rect.CREATOR.createFromParcel(in);
+ stableInsets = Rect.CREATOR.createFromParcel(in);
+ }
+
+ /** Needed for AIDL out parameters. */
+ public void readFromParcel(Parcel in) {
+ frame.set(Rect.CREATOR.createFromParcel(in));
+ displayFrame.set(Rect.CREATOR.createFromParcel(in));
+ backdropFrame.set(Rect.CREATOR.createFromParcel(in));
+ displayCutout.set(DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in));
+ contentInsets.set(Rect.CREATOR.createFromParcel(in));
+ visibleInsets.set(Rect.CREATOR.createFromParcel(in));
+ stableInsets.set(Rect.CREATOR.createFromParcel(in));
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ frame.writeToParcel(dest, flags);
+ displayFrame.writeToParcel(dest, flags);
+ backdropFrame.writeToParcel(dest, flags);
+ displayCutout.writeToParcel(dest, flags);
+ contentInsets.writeToParcel(dest, flags);
+ visibleInsets.writeToParcel(dest, flags);
+ stableInsets.writeToParcel(dest, flags);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder(32);
+ return "ClientWindowFrames{frame=" + frame.toShortString(sb)
+ + " display=" + displayFrame.toShortString(sb)
+ + " backdrop=" + backdropFrame.toShortString(sb)
+ + " cutout=" + displayCutout + "}";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<ClientWindowFrames> CREATOR = new Creator<ClientWindowFrames>() {
+ public ClientWindowFrames createFromParcel(Parcel in) {
+ return new ClientWindowFrames(in);
+ }
+
+ public ClientWindowFrames[] newArray(int size) {
+ return new ClientWindowFrames[size];
+ }
+ };
+}
diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
index 9013da3..db27d62 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -25,6 +25,7 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.ActivityView;
import android.app.TaskStackListener;
import android.content.ComponentName;
@@ -357,40 +358,40 @@
private class TaskStackListenerImpl extends TaskStackListener {
@Override
- public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo runningTaskInfo)
throws RemoteException {
if (!isInitialized()) {
return;
}
- if (taskInfo.displayId != getDisplayId()) {
+ if (runningTaskInfo.displayId != getDisplayId()) {
return;
}
- ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
- if (stackInfo == null) {
+ RootTaskInfo taskInfo = getTopMostRootTaskInfo();
+ if (taskInfo == null) {
return;
}
// Found the topmost stack on target display. Now check if the topmost task's
// description changed.
- if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ if (runningTaskInfo.taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) {
mHost.post(()-> mHost.onTaskBackgroundColorChanged(VirtualDisplayTaskEmbedder.this,
- taskInfo.taskDescription.getBackgroundColor()));
+ runningTaskInfo.taskDescription.getBackgroundColor()));
}
}
@Override
- public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo runningTaskInfo)
throws RemoteException {
if (!isInitialized() || mListener == null
- || taskInfo.displayId != getDisplayId()) {
+ || runningTaskInfo.displayId != getDisplayId()) {
return;
}
- ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or unrelated to the "move to front" then there's no use
+ RootTaskInfo taskInfo = getTopMostRootTaskInfo();
+ // if TaskInfo was null or unrelated to the "move to front" then there's no use
// notifying the callback
- if (stackInfo != null
- && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mListener.onTaskMovedToFront(taskInfo.taskId);
+ if (taskInfo != null && runningTaskInfo.taskId == taskInfo.childTaskIds[
+ taskInfo.childTaskIds.length - 1]) {
+ mListener.onTaskMovedToFront(runningTaskInfo.taskId);
}
}
@@ -400,11 +401,11 @@
return;
}
- ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or unrelated to the task creation then there's no use
+ RootTaskInfo taskInfo = getTopMostRootTaskInfo();
+ // if TaskInfo was null or unrelated to the task creation then there's no use
// notifying the callback
- if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ if (taskInfo != null
+ && taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) {
mListener.onTaskCreated(taskId, componentName);
}
}
@@ -420,16 +421,16 @@
mListener.onTaskRemovalStarted(taskInfo.taskId);
}
- private ActivityManager.StackInfo getTopMostStackInfo() throws RemoteException {
+ private RootTaskInfo getTopMostRootTaskInfo() throws RemoteException {
// Find the topmost task on our virtual display - it will define the background
// color of the surface view during resizing.
final int displayId = getDisplayId();
- final List<ActivityManager.StackInfo> stackInfoList =
- mActivityTaskManager.getAllStackInfosOnDisplay(displayId);
- if (stackInfoList.isEmpty()) {
+ final List<RootTaskInfo> taskInfoList =
+ mActivityTaskManager.getAllRootTaskInfosOnDisplay(displayId);
+ if (taskInfoList.isEmpty()) {
return null;
}
- return stackInfoList.get(0);
+ return taskInfoList.get(0);
}
}
}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index da26930..8b4fddb 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -390,9 +390,9 @@
public static final String CHOOSER_TARGET_RANKING_ENABLED = "chooser_target_ranking_enabled";
/**
- * (boolean) Whether to enable user-drag resizing for PIP.
+ * (boolean) Whether to enable pinch resizing for PIP.
*/
- public static final String PIP_USER_RESIZE = "pip_user_resize";
+ public static final String PIP_PINCH_RESIZE = "pip_pinch_resize";
/**
* (float) Bottom height in DP for Back Gesture.
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 3b5cf48..b38f623e 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -296,7 +296,7 @@
if (p.getOverlayTarget() != null && isSystem) {
overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(),
p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(),
- new File(p.getBaseCodePath())));
+ new File(p.getBaseApkPath())));
}
});
return overlays;
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index e5c8450..dd1978e 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -45,8 +45,8 @@
private long mBeginTime = UNKNOWN_TIMESTAMP;
private long mEndTime = UNKNOWN_TIMESTAMP;
private boolean mShouldTriggerTrace;
- private long mTotalFramesCount = 0;
- private long mMissedFramesCount = 0;
+ private int mTotalFramesCount = 0;
+ private int mMissedFramesCount = 0;
private long mMaxFrameTimeNanos = 0;
private Session mSession;
@@ -124,6 +124,15 @@
if (mEndTime != UNKNOWN_TIMESTAMP && vsyncTimestamp > mEndTime) {
// The tracing has been ended, remove the observer, see if need to trigger perfetto.
mRendererWrapper.removeObserver(mObserver);
+
+ // Log the frame stats as counters to make them easily accessible in traces.
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames",
+ mMissedFramesCount);
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
+ mTotalFramesCount);
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis",
+ (int) (mMaxFrameTimeNanos / 1_000_000));
+
// Trigger perfetto if necessary.
if (mShouldTriggerTrace) {
if (DEBUG) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8498151..e58990e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -73,6 +73,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.KeyValueListParser;
import android.util.Log;
@@ -256,7 +257,7 @@
@GuardedBy("this")
private long mNumBatchedSingleUidCpuTimeReads;
@GuardedBy("this")
- private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
+ private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
@GuardedBy("this")
private int mNumUidsRemoved;
@GuardedBy("this")
@@ -290,7 +291,7 @@
public final class UidToRemove {
int startUid;
int endUid;
- long timeAddedInQueue;
+ long mTimeAddedInQueueMs;
/** Remove just one UID */
public UidToRemove(int uid, long timestamp) {
@@ -301,7 +302,7 @@
public UidToRemove(int startUid, int endUid, long timestamp) {
this.startUid = startUid;
this.endUid = endUid;
- timeAddedInQueue = timestamp;
+ mTimeAddedInQueueMs = timestamp;
}
void remove() {
@@ -382,9 +383,9 @@
}
boolean changed = setChargingLocked(true);
if (changed) {
- final long uptime = mClocks.uptimeMillis();
- final long elapsedRealtime = mClocks.elapsedRealtime();
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ final long uptimeMs = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -502,9 +503,9 @@
}
public void clearPendingRemovedUids() {
- long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
+ long cutOffTimeMs = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
while (!mPendingRemovedUids.isEmpty()
- && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
+ && mPendingRemovedUids.peek().mTimeAddedInQueueMs < cutOffTimeMs) {
mPendingRemovedUids.poll().remove();
}
}
@@ -572,7 +573,7 @@
}
@VisibleForTesting
- public long[] addCpuTimes(long[] timesA, long[] timesB) {
+ public static long[] addCpuTimes(long[] timesA, long[] timesB) {
if (timesA != null && timesB != null) {
for (int i = timesA.length - 1; i >= 0; --i) {
timesA[i] += timesB[i];
@@ -700,7 +701,7 @@
final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
- long mHistoryBaseTime;
+ long mHistoryBaseTimeMs;
protected boolean mHaveBatteryLevel = false;
protected boolean mRecordingHistory = false;
int mNumHistoryItems;
@@ -719,9 +720,9 @@
int mHistoryBufferLastPos = -1;
int mActiveHistoryStates = 0xffffffff;
int mActiveHistoryStates2 = 0xffffffff;
- long mLastHistoryElapsedRealtime = 0;
- long mTrackRunningHistoryElapsedRealtime = 0;
- long mTrackRunningHistoryUptime = 0;
+ long mLastHistoryElapsedRealtimeMs = 0;
+ long mTrackRunningHistoryElapsedRealtimeMs = 0;
+ long mTrackRunningHistoryUptimeMs = 0;
final BatteryStatsHistory mBatteryStatsHistory;
@@ -742,28 +743,28 @@
/**
* Total time (in milliseconds) spent executing in user code.
*/
- long mLastStepCpuUserTime;
- long mCurStepCpuUserTime;
+ long mLastStepCpuUserTimeMs;
+ long mCurStepCpuUserTimeMs;
/**
* Total time (in milliseconds) spent executing in kernel code.
*/
- long mLastStepCpuSystemTime;
- long mCurStepCpuSystemTime;
+ long mLastStepCpuSystemTimeMs;
+ long mCurStepCpuSystemTimeMs;
/**
* Times from /proc/stat (but measured in milliseconds).
*/
- long mLastStepStatUserTime;
- long mLastStepStatSystemTime;
- long mLastStepStatIOWaitTime;
- long mLastStepStatIrqTime;
- long mLastStepStatSoftIrqTime;
- long mLastStepStatIdleTime;
- long mCurStepStatUserTime;
- long mCurStepStatSystemTime;
- long mCurStepStatIOWaitTime;
- long mCurStepStatIrqTime;
- long mCurStepStatSoftIrqTime;
- long mCurStepStatIdleTime;
+ long mLastStepStatUserTimeMs;
+ long mLastStepStatSystemTimeMs;
+ long mLastStepStatIOWaitTimeMs;
+ long mLastStepStatIrqTimeMs;
+ long mLastStepStatSoftIrqTimeMs;
+ long mLastStepStatIdleTimeMs;
+ long mCurStepStatUserTimeMs;
+ long mCurStepStatSystemTimeMs;
+ long mCurStepStatIOWaitTimeMs;
+ long mCurStepStatIrqTimeMs;
+ long mCurStepStatSoftIrqTimeMs;
+ long mCurStepStatIdleTimeMs;
private HistoryItem mHistoryIterator;
private boolean mReadOverflow;
@@ -771,14 +772,14 @@
int mStartCount;
- long mStartClockTime;
+ long mStartClockTimeMs;
String mStartPlatformVersion;
String mEndPlatformVersion;
- long mUptime;
- long mUptimeStart;
- long mRealtime;
- long mRealtimeStart;
+ long mUptimeUs;
+ long mUptimeStartUs;
+ long mRealtimeUs;
+ long mRealtimeStartUs;
int mWakeLockNesting;
boolean mWakeLockImportant;
@@ -810,9 +811,9 @@
StopwatchTimer mDeviceLightIdlingTimer;
int mDeviceIdleMode;
- long mLastIdleTimeStart;
- long mLongestLightIdleTime;
- long mLongestFullIdleTime;
+ long mLastIdleTimeStartMs;
+ long mLongestLightIdleTimeMs;
+ long mLongestFullIdleTimeMs;
StopwatchTimer mDeviceIdleModeLightTimer;
StopwatchTimer mDeviceIdleModeFullTimer;
@@ -921,7 +922,7 @@
protected StopwatchTimer mBluetoothScanTimer;
int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
- long mMobileRadioActiveStartTime;
+ long mMobileRadioActiveStartTimeMs;
StopwatchTimer mMobileRadioActiveTimer;
StopwatchTimer mMobileRadioActivePerAppTimer;
LongSamplingCounter mMobileRadioActiveAdjustedTime;
@@ -989,13 +990,13 @@
static final int MAX_DAILY_ITEMS = 10;
- long mDailyStartTime = 0;
- long mNextMinDailyDeadline = 0;
- long mNextMaxDailyDeadline = 0;
+ long mDailyStartTimeMs = 0;
+ long mNextMinDailyDeadlineMs = 0;
+ long mNextMaxDailyDeadlineMs = 0;
final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
- long mLastWriteTime = 0; // Milliseconds
+ long mLastWriteTimeMs = 0; // Milliseconds
private int mPhoneServiceState = -1;
private int mPhoneServiceStateRaw = -1;
@@ -1131,8 +1132,8 @@
* TimeBase observer.
*/
public interface TimeBaseObs {
- void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
- void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
+ void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
+ void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
/**
* Reset the observer's state, returns true if the timer/counter is inactive
@@ -1140,7 +1141,18 @@
* @param detachIfReset detach if true, no-op if false.
* @return Returns true if the timer/counter is inactive and can be destroyed.
*/
- boolean reset(boolean detachIfReset);
+ default boolean reset(boolean detachIfReset) {
+ return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #reset(boolean)
+ * @param detachIfReset detach if true, no-op if false.
+ * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
+ * @return Returns true if the timer/counter is inactive and can be destroyed.
+ */
+ boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
+
/**
* Detach the observer from TimeBase.
*/
@@ -1150,17 +1162,19 @@
// methods are protected not private to be VisibleForTesting
public static class TimeBase {
protected final Collection<TimeBaseObs> mObservers;
- protected long mUptime;
- protected long mRealtime;
+
+ // All below time metrics are in microseconds.
+ protected long mUptimeUs;
+ protected long mRealtimeUs;
protected boolean mRunning;
- protected long mPastUptime;
- protected long mUptimeStart;
- protected long mPastRealtime;
- protected long mRealtimeStart;
- protected long mUnpluggedUptime;
- protected long mUnpluggedRealtime;
+ protected long mPastUptimeUs;
+ protected long mUptimeStartUs;
+ protected long mPastRealtimeUs;
+ protected long mRealtimeStartUs;
+ protected long mUnpluggedUptimeUs;
+ protected long mUnpluggedRealtimeUs;
public void dump(PrintWriter pw, String prefix) {
StringBuilder sb = new StringBuilder(128);
@@ -1168,26 +1182,26 @@
sb.setLength(0);
sb.append(prefix);
sb.append("mUptime=");
- formatTimeMs(sb, mUptime / 1000);
+ formatTimeMs(sb, mUptimeUs / 1000);
pw.println(sb.toString());
sb.setLength(0);
sb.append(prefix);
sb.append("mRealtime=");
- formatTimeMs(sb, mRealtime / 1000);
+ formatTimeMs(sb, mRealtimeUs / 1000);
pw.println(sb.toString());
sb.setLength(0);
sb.append(prefix);
sb.append("mPastUptime=");
- formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
- formatTimeMs(sb, mUptimeStart / 1000);
- sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
+ formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
+ formatTimeMs(sb, mUptimeStartUs / 1000);
+ sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
pw.println(sb.toString());
sb.setLength(0);
sb.append(prefix);
sb.append("mPastRealtime=");
- formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
- formatTimeMs(sb, mRealtimeStart / 1000);
- sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
+ formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
+ formatTimeMs(sb, mRealtimeStartUs / 1000);
+ sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
pw.println(sb.toString());
}
/**
@@ -1219,94 +1233,96 @@
return mObservers.contains(observer);
}
- public void init(long uptime, long realtime) {
- mRealtime = 0;
- mUptime = 0;
- mPastUptime = 0;
- mPastRealtime = 0;
- mUptimeStart = uptime;
- mRealtimeStart = realtime;
- mUnpluggedUptime = getUptime(mUptimeStart);
- mUnpluggedRealtime = getRealtime(mRealtimeStart);
+ public void init(long uptimeUs, long elapsedRealtimeUs) {
+ mRealtimeUs = 0;
+ mUptimeUs = 0;
+ mPastUptimeUs = 0;
+ mPastRealtimeUs = 0;
+ mUptimeStartUs = uptimeUs;
+ mRealtimeStartUs = elapsedRealtimeUs;
+ mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
+ mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
}
- public void reset(long uptime, long realtime) {
+ public void reset(long uptimeUs, long elapsedRealtimeUs) {
if (!mRunning) {
- mPastUptime = 0;
- mPastRealtime = 0;
+ mPastUptimeUs = 0;
+ mPastRealtimeUs = 0;
} else {
- mUptimeStart = uptime;
- mRealtimeStart = realtime;
- // TODO: Since mUptimeStart was just reset and we are running, getUptime will
- // just return mPastUptime. Also, are we sure we don't want to reset that?
- mUnpluggedUptime = getUptime(uptime);
+ mUptimeStartUs = uptimeUs;
+ mRealtimeStartUs = elapsedRealtimeUs;
+ // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
+ // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
+ mUnpluggedUptimeUs = getUptime(uptimeUs);
// TODO: likewise.
- mUnpluggedRealtime = getRealtime(realtime);
+ mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
}
}
- public long computeUptime(long curTime, int which) {
- return mUptime + getUptime(curTime);
+ public long computeUptime(long curTimeUs, int which) {
+ return mUptimeUs + getUptime(curTimeUs);
}
- public long computeRealtime(long curTime, int which) {
- return mRealtime + getRealtime(curTime);
+ public long computeRealtime(long curTimeUs, int which) {
+ return mRealtimeUs + getRealtime(curTimeUs);
}
- public long getUptime(long curTime) {
- long time = mPastUptime;
+ public long getUptime(long curTimeUs) {
+ long time = mPastUptimeUs;
if (mRunning) {
- time += curTime - mUptimeStart;
+ time += curTimeUs - mUptimeStartUs;
}
return time;
}
- public long getRealtime(long curTime) {
- long time = mPastRealtime;
+ public long getRealtime(long curTimeUs) {
+ long time = mPastRealtimeUs;
if (mRunning) {
- time += curTime - mRealtimeStart;
+ time += curTimeUs - mRealtimeStartUs;
}
return time;
}
public long getUptimeStart() {
- return mUptimeStart;
+ return mUptimeStartUs;
}
public long getRealtimeStart() {
- return mRealtimeStart;
+ return mRealtimeStartUs;
}
public boolean isRunning() {
return mRunning;
}
- public boolean setRunning(boolean running, long uptime, long realtime) {
+ public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
if (mRunning != running) {
mRunning = running;
if (running) {
- mUptimeStart = uptime;
- mRealtimeStart = realtime;
- long batteryUptime = mUnpluggedUptime = getUptime(uptime);
- long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
+ mUptimeStartUs = uptimeUs;
+ mRealtimeStartUs = elapsedRealtimeUs;
+ long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
+ long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
// Normally we do not use Iterator in framework code to avoid alloc/dealloc
// Iterator object, here is an exception because mObservers' type is Collection
// instead of list.
final Iterator<TimeBaseObs> iter = mObservers.iterator();
while (iter.hasNext()) {
- iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
+ iter.next().onTimeStarted(
+ elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
}
} else {
- mPastUptime += uptime - mUptimeStart;
- mPastRealtime += realtime - mRealtimeStart;
- long batteryUptime = getUptime(uptime);
- long batteryRealtime = getRealtime(realtime);
+ mPastUptimeUs += uptimeUs - mUptimeStartUs;
+ mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
+ long batteryUptimeUs = getUptime(uptimeUs);
+ long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
// Normally we do not use Iterator in framework code to avoid alloc/dealloc
// Iterator object, here is an exception because mObservers' type is Collection
// instead of list.
final Iterator<TimeBaseObs> iter = mObservers.iterator();
while (iter.hasNext()) {
- iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
+ iter.next().onTimeStopped(
+ elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
}
}
return true;
@@ -1315,38 +1331,38 @@
}
public void readSummaryFromParcel(Parcel in) {
- mUptime = in.readLong();
- mRealtime = in.readLong();
+ mUptimeUs = in.readLong();
+ mRealtimeUs = in.readLong();
}
- public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
- out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
- out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
+ public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
+ out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
+ out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
}
public void readFromParcel(Parcel in) {
mRunning = false;
- mUptime = in.readLong();
- mPastUptime = in.readLong();
- mUptimeStart = in.readLong();
- mRealtime = in.readLong();
- mPastRealtime = in.readLong();
- mRealtimeStart = in.readLong();
- mUnpluggedUptime = in.readLong();
- mUnpluggedRealtime = in.readLong();
+ mUptimeUs = in.readLong();
+ mPastUptimeUs = in.readLong();
+ mUptimeStartUs = in.readLong();
+ mRealtimeUs = in.readLong();
+ mPastRealtimeUs = in.readLong();
+ mRealtimeStartUs = in.readLong();
+ mUnpluggedUptimeUs = in.readLong();
+ mUnpluggedRealtimeUs = in.readLong();
}
- public void writeToParcel(Parcel out, long uptime, long realtime) {
- final long runningUptime = getUptime(uptime);
- final long runningRealtime = getRealtime(realtime);
- out.writeLong(mUptime);
+ public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
+ final long runningUptime = getUptime(uptimeUs);
+ final long runningRealtime = getRealtime(elapsedRealtimeUs);
+ out.writeLong(mUptimeUs);
out.writeLong(runningUptime);
- out.writeLong(mUptimeStart);
- out.writeLong(mRealtime);
+ out.writeLong(mUptimeStartUs);
+ out.writeLong(mRealtimeUs);
out.writeLong(runningRealtime);
- out.writeLong(mRealtimeStart);
- out.writeLong(mUnpluggedUptime);
- out.writeLong(mUnpluggedRealtime);
+ out.writeLong(mRealtimeStartUs);
+ out.writeLong(mUnpluggedUptimeUs);
+ out.writeLong(mUnpluggedRealtimeUs);
}
}
@@ -1374,11 +1390,11 @@
}
@Override
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
/**
@@ -1436,7 +1452,7 @@
* Clear state of this counter.
*/
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
mCount.set(0);
if (detachIfReset) {
detach();
@@ -1481,11 +1497,11 @@
}
@Override
- public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
@Override
@@ -1524,7 +1540,7 @@
* Clear state of this counter.
*/
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
if (mCounts != null) {
Arrays.fill(mCounts, 0);
}
@@ -1608,11 +1624,11 @@
}
@Override
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
}
public long getCountLocked(int which) {
@@ -1638,7 +1654,7 @@
* Clear state of this counter.
*/
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
mCount = 0;
if (detachIfReset) {
detach();
@@ -1678,13 +1694,13 @@
* boot, to the last time something interesting happened in the
* current run.
*/
- protected long mTotalTime;
+ protected long mTotalTimeUs;
/**
* The total time this timer has been running until the latest mark has been set.
- * Subtract this from mTotalTime to get the time spent running since the mark was set.
+ * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
*/
- protected long mTimeBeforeMark;
+ protected long mTimeBeforeMarkUs;
/**
* Constructs from a parcel.
@@ -1698,10 +1714,10 @@
mTimeBase = timeBase;
mCount = in.readInt();
- mTotalTime = in.readLong();
- mTimeBeforeMark = in.readLong();
+ mTotalTimeUs = in.readLong();
+ mTimeBeforeMarkUs = in.readLong();
timeBase.add(this);
- if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
+ if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
}
public Timer(Clocks clocks, int type, TimeBase timeBase) {
@@ -1714,14 +1730,17 @@
public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
if (DEBUG) {
Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
- + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
+ + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
+ elapsedRealtimeUs));
}
out.writeInt(computeCurrentCountLocked());
- out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
- out.writeLong(mTimeBeforeMark);
+ out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
+ elapsedRealtimeUs));
+ out.writeLong(mTimeBeforeMarkUs);
}
- protected abstract long computeRunTimeLocked(long curBatteryRealtime);
+ protected abstract long computeRunTimeLocked(long curBatteryRealtime,
+ long elapsedRealtimeUs);
protected abstract int computeCurrentCountLocked();
@@ -1731,7 +1750,12 @@
*/
@Override
public boolean reset(boolean detachIfReset) {
- mTotalTime = mTimeBeforeMark = 0;
+ return reset(detachIfReset, mClocks.elapsedRealtime() * 1000);
+ }
+
+ @Override
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
+ mTotalTimeUs = mTimeBeforeMarkUs = 0;
mCount = 0;
if (detachIfReset) {
detach();
@@ -1745,19 +1769,20 @@
}
@Override
- public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
+ long baseRealtimeUs) {
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
if (DEBUG && mType < 0) {
- Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
- + " old mTotalTime=" + mTotalTime);
+ Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
+ + " old mTotalTime=" + mTotalTimeUs);
}
- mTotalTime = computeRunTimeLocked(baseRealtime);
+ mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
mCount = computeCurrentCountLocked();
if (DEBUG && mType < 0) {
- Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime);
+ Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
}
}
@@ -1780,7 +1805,8 @@
@Override
@UnsupportedAppUsage
public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
- return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
+ return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
+ elapsedRealtimeUs);
}
@Override
@@ -1791,29 +1817,31 @@
@Override
public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
- long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
- return val - mTimeBeforeMark;
+ long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
+ elapsedRealtimeUs);
+ return val - mTimeBeforeMarkUs;
}
@Override
public void logState(Printer pw, String prefix) {
pw.println(prefix + "mCount=" + mCount);
- pw.println(prefix + "mTotalTime=" + mTotalTime);
+ pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
}
public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
- long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
- out.writeLong(runTime);
+ long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
+ elapsedRealtimeUs);
+ out.writeLong(runTimeUs);
out.writeInt(computeCurrentCountLocked());
}
public void readSummaryFromParcelLocked(Parcel in) {
// Multiply by 1000 for backwards compatibility
- mTotalTime = in.readLong();
+ mTotalTimeUs = in.readLong();
mCount = in.readInt();
// When reading the summary, we set the mark to be the latest information.
- mTimeBeforeMark = mTotalTime;
+ mTimeBeforeMarkUs = mTotalTimeUs;
}
}
@@ -1843,14 +1871,14 @@
/**
* The most recent reported total_time from /proc/wakelocks.
*/
- long mCurrentReportedTotalTime;
+ long mCurrentReportedTotalTimeUs;
/**
* The reported total_time from /proc/wakelocks when unplug() was last
* called.
*/
- long mUnpluggedReportedTotalTime;
+ long mUnpluggedReportedTotalTimeUs;
/**
* Whether we are currently in a discharge cycle.
@@ -1872,8 +1900,8 @@
super(clocks, 0, timeBase, in);
mCurrentReportedCount = in.readInt();
mUnpluggedReportedCount = in.readInt();
- mCurrentReportedTotalTime = in.readLong();
- mUnpluggedReportedTotalTime = in.readLong();
+ mCurrentReportedTotalTimeUs = in.readLong();
+ mUnpluggedReportedTotalTimeUs = in.readLong();
mTrackingReportedValues = in.readInt() == 1;
mTimeBaseRunning = timeBase.isRunning();
}
@@ -1890,9 +1918,16 @@
* be less than the values used for a previous invocation.
*/
public void endSample() {
- mTotalTime = computeRunTimeLocked(0 /* unused by us */);
+ endSample(mClocks.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #endSample()
+ */
+ public void endSample(long elapsedRealtimeUs) {
+ mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
mCount = computeCurrentCountLocked();
- mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
+ mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
mUnpluggedReportedCount = mCurrentReportedCount = 0;
mTrackingReportedValues = false;
}
@@ -1911,26 +1946,33 @@
*
* If the values being recorded have been reset, the monotonically increasing requirement
* will be broken. In this case, {@link #endSample()} is automatically called and
- * the total value of totalTime and count are recorded, starting a new monotonically
+ * the total value of totalTimeUs and count are recorded, starting a new monotonically
* increasing sample.
*
- * @param totalTime total time of sample in microseconds.
+ * @param totalTimeUs total time of sample in microseconds.
* @param count total number of times the event being sampled occurred.
*/
- public void update(long totalTime, int count) {
+ public void updated(long totalTimeUs, int count) {
+ update(totalTimeUs, count, mClocks.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #update(long, int)
+ */
+ public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
if (mTimeBaseRunning && !mTrackingReportedValues) {
// Updating the reported value for the first time.
- mUnpluggedReportedTotalTime = totalTime;
+ mUnpluggedReportedTotalTimeUs = totalTimeUs;
mUnpluggedReportedCount = count;
}
mTrackingReportedValues = true;
- if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
- endSample();
+ if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
+ endSample(elapsedRealtimeUs);
}
- mCurrentReportedTotalTime = totalTime;
+ mCurrentReportedTotalTimeUs = totalTimeUs;
mCurrentReportedCount = count;
}
@@ -1940,23 +1982,31 @@
* @param deltaTime additional time recorded since the last sampled event, in microseconds.
* @param deltaCount additional number of times the event being sampled occurred.
*/
- public void add(long deltaTime, int deltaCount) {
- update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
+ public void add(long deltaTimeUs, int deltaCount) {
+ add(deltaTimeUs, deltaCount, mClocks.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #add(long, int)
+ */
+ public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
+ update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
+ elapsedRealtimeUs);
}
@Override
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
- super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
if (mTrackingReportedValues) {
- mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
+ mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
mUnpluggedReportedCount = mCurrentReportedCount;
}
mTimeBaseRunning = true;
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
- super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
mTimeBaseRunning = false;
}
@@ -1965,14 +2015,14 @@
super.logState(pw, prefix);
pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
+ " mUnpluggedReportedCount=" + mUnpluggedReportedCount
- + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
- + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
+ + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
+ + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
}
@Override
- protected long computeRunTimeLocked(long curBatteryRealtime) {
- return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
- ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
+ protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
+ return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
+ ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
}
@Override
@@ -1986,16 +2036,16 @@
super.writeToParcel(out, elapsedRealtimeUs);
out.writeInt(mCurrentReportedCount);
out.writeInt(mUnpluggedReportedCount);
- out.writeLong(mCurrentReportedTotalTime);
- out.writeLong(mUnpluggedReportedTotalTime);
+ out.writeLong(mCurrentReportedTotalTimeUs);
+ out.writeLong(mUnpluggedReportedTotalTimeUs);
out.writeInt(mTrackingReportedValues ? 1 : 0);
}
@Override
- public boolean reset(boolean detachIfReset) {
- super.reset(detachIfReset);
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
+ super.reset(detachIfReset, elapsedRealtimeUs);
mTrackingReportedValues = false;
- mUnpluggedReportedTotalTime = 0;
+ mUnpluggedReportedTotalTimeUs = 0;
mUnpluggedReportedCount = 0;
return true;
}
@@ -2011,12 +2061,12 @@
/**
* The last time at which we updated the timer. This is in elapsed realtime microseconds.
*/
- long mLastAddedTime;
+ long mLastAddedTimeUs;
/**
* The last duration that we added to the timer. This is in microseconds.
*/
- long mLastAddedDuration;
+ long mLastAddedDurationUs;
/**
* Whether we are currently in a discharge cycle.
@@ -2026,8 +2076,8 @@
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
super(clocks, type, timeBase, in);
mUid = uid;
- mLastAddedTime = in.readLong();
- mLastAddedDuration = in.readLong();
+ mLastAddedTimeUs = in.readLong();
+ mLastAddedDurationUs = in.readLong();
mInDischarge = timeBase.isRunning();
}
@@ -2040,74 +2090,82 @@
@Override
public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
super.writeToParcel(out, elapsedRealtimeUs);
- out.writeLong(mLastAddedTime);
- out.writeLong(mLastAddedDuration);
+ out.writeLong(mLastAddedTimeUs);
+ out.writeLong(mLastAddedDurationUs);
}
@Override
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
- recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ recomputeLastDuration(elapsedRealtimeUs, false);
mInDischarge = false;
- super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
+ super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
}
@Override
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
- recomputeLastDuration(elapsedRealtime, false);
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ recomputeLastDuration(elapsedRealtimeUs, false);
mInDischarge = true;
// If we are still within the last added duration, then re-added whatever remains.
- if (mLastAddedTime == elapsedRealtime) {
- mTotalTime += mLastAddedDuration;
+ if (mLastAddedTimeUs == elapsedRealtimeUs) {
+ mTotalTimeUs += mLastAddedDurationUs;
}
- super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
+ super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
}
@Override
public void logState(Printer pw, String prefix) {
super.logState(pw, prefix);
- pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
- + " mLastAddedDuration=" + mLastAddedDuration);
+ pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
+ + " mLastAddedDuration=" + mLastAddedDurationUs);
}
- private long computeOverage(long curTime) {
- if (mLastAddedTime > 0) {
- return mLastAddedDuration - curTime;
+ private long computeOverage(long curTimeUs) {
+ if (mLastAddedTimeUs > 0) {
+ return mLastAddedDurationUs - curTimeUs;
}
return 0;
}
- private void recomputeLastDuration(long curTime, boolean abort) {
- final long overage = computeOverage(curTime);
+ private void recomputeLastDuration(long curTimeUs, boolean abort) {
+ final long overage = computeOverage(curTimeUs);
if (overage > 0) {
// Aborting before the duration ran out -- roll back the remaining
// duration. Only do this if currently discharging; otherwise we didn't
// actually add the time.
if (mInDischarge) {
- mTotalTime -= overage;
+ mTotalTimeUs -= overage;
}
if (abort) {
- mLastAddedTime = 0;
+ mLastAddedTimeUs = 0;
} else {
- mLastAddedTime = curTime;
- mLastAddedDuration -= overage;
+ mLastAddedTimeUs = curTimeUs;
+ mLastAddedDurationUs -= overage;
}
}
}
- public void addDuration(BatteryStatsImpl stats, long durationMillis) {
- final long now = mClocks.elapsedRealtime() * 1000;
- recomputeLastDuration(now, true);
- mLastAddedTime = now;
- mLastAddedDuration = durationMillis * 1000;
+ public void addDuration(BatteryStatsImpl stats, long durationMs) {
+ addDuration(stats, durationMs, mClocks.elapsedRealtime());
+ }
+
+ public void addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs) {
+ final long nowUs = elapsedRealtimeMs * 1000;
+ recomputeLastDuration(nowUs, true);
+ mLastAddedTimeUs = nowUs;
+ mLastAddedDurationUs = durationMs * 1000;
if (mInDischarge) {
- mTotalTime += mLastAddedDuration;
+ mTotalTimeUs += mLastAddedDurationUs;
mCount++;
}
}
public void abortLastDuration(BatteryStatsImpl stats) {
- final long now = mClocks.elapsedRealtime() * 1000;
- recomputeLastDuration(now, true);
+ abortLastDuration(stats, mClocks.elapsedRealtime());
+ }
+
+ public void abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs) {
+ final long nowUs = elapsedRealtimeMs * 1000;
+ recomputeLastDuration(nowUs, true);
}
@Override
@@ -2116,20 +2174,19 @@
}
@Override
- protected long computeRunTimeLocked(long curBatteryRealtime) {
- final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
+ protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
+ final long overage = computeOverage(elapsedRealtimeUs);
if (overage > 0) {
- return mTotalTime = overage;
+ return mTotalTimeUs = overage;
}
- return mTotalTime;
+ return mTotalTimeUs;
}
@Override
- public boolean reset(boolean detachIfReset) {
- final long now = mClocks.elapsedRealtime() * 1000;
- recomputeLastDuration(now, true);
- boolean stillActive = mLastAddedTime == now;
- super.reset(!stillActive && detachIfReset);
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
+ recomputeLastDuration(elapsedRealtimeUs, true);
+ boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
+ super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
return !stillActive;
}
}
@@ -2225,10 +2282,10 @@
*
* If the timer is also running, store the start time.
*/
- public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
- super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
if (mNesting > 0) {
- mStartTimeMs = baseRealtime / 1000;
+ mStartTimeMs = baseRealtimeUs / 1000;
}
}
@@ -2238,8 +2295,8 @@
* If the timer is running, add the duration into mCurrentDurationMs.
*/
@Override
- public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
- super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
+ super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
if (mNesting > 0) {
// baseRealtimeUs has already been converted to the timebase's realtime.
mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
@@ -2284,13 +2341,13 @@
}
@Override
- public boolean reset(boolean detachIfReset) {
- boolean result = super.reset(detachIfReset);
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
+ boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
mMaxDurationMs = 0;
mTotalDurationMs = 0;
mCurrentDurationMs = 0;
if (mNesting > 0) {
- mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000;
+ mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
} else {
mStartTimeMs = -1;
}
@@ -2364,16 +2421,16 @@
* subtract this from the current battery time to find the amount of
* time we have been running since we last computed an update.
*/
- long mUpdateTime;
+ long mUpdateTimeUs;
/**
* The total time at which the timer was acquired, to determine if it
* was actually held for an interesting duration. If time base was not running when timer
* was acquired, will be -1.
*/
- long mAcquireTime = -1;
+ long mAcquireTimeUs = -1;
- long mTimeout;
+ long mTimeoutUs;
/**
* For partial wake locks, keep track of whether we are in the list
@@ -2387,7 +2444,7 @@
super(clocks, type, timeBase, in);
mUid = uid;
mTimerPool = timerPool;
- mUpdateTime = in.readLong();
+ mUpdateTimeUs = in.readLong();
}
public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
@@ -2397,56 +2454,56 @@
mTimerPool = timerPool;
}
- public void setTimeout(long timeout) {
- mTimeout = timeout;
+ public void setTimeout(long timeoutUs) {
+ mTimeoutUs = timeoutUs;
}
public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
super.writeToParcel(out, elapsedRealtimeUs);
- out.writeLong(mUpdateTime);
+ out.writeLong(mUpdateTimeUs);
}
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
if (mNesting > 0) {
if (DEBUG && mType < 0) {
- Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
+ Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
}
- super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
- mUpdateTime = baseRealtime;
+ super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
+ mUpdateTimeUs = baseRealtimeUs;
if (DEBUG && mType < 0) {
- Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
+ Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
}
}
}
public void logState(Printer pw, String prefix) {
super.logState(pw, prefix);
- pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
- + " mAcquireTime=" + mAcquireTime);
+ pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
+ + " mAcquireTime=" + mAcquireTimeUs);
}
public void startRunningLocked(long elapsedRealtimeMs) {
if (mNesting++ == 0) {
- final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
- mUpdateTime = batteryRealtime;
+ final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
+ mUpdateTimeUs = batteryRealtimeUs;
if (mTimerPool != null) {
// Accumulate time to all currently active timers before adding
// this new one to the pool.
- refreshTimersLocked(batteryRealtime, mTimerPool, null);
+ refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
// Add this timer to the active pool
mTimerPool.add(this);
}
if (mTimeBase.isRunning()) {
// Increment the count
mCount++;
- mAcquireTime = mTotalTime;
+ mAcquireTimeUs = mTotalTimeUs;
} else {
- mAcquireTime = -1;
+ mAcquireTimeUs = -1;
}
if (DEBUG && mType < 0) {
- Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
- + " mTotalTime=" + mTotalTime + " mCount=" + mCount
- + " mAcquireTime=" + mAcquireTime);
+ Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
+ + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
+ + " mAcquireTime=" + mAcquireTimeUs);
}
}
}
@@ -2461,26 +2518,27 @@
return;
}
if (--mNesting == 0) {
- final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
+ final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
if (mTimerPool != null) {
// Accumulate time to all active counters, scaled by the total
// active in the pool, before taking this one out of the pool.
- refreshTimersLocked(batteryRealtime, mTimerPool, null);
+ refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
// Remove this timer from the active pool
mTimerPool.remove(this);
} else {
mNesting = 1;
- mTotalTime = computeRunTimeLocked(batteryRealtime);
+ mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
+ elapsedRealtimeMs * 1000);
mNesting = 0;
}
if (DEBUG && mType < 0) {
- Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
- + " mTotalTime=" + mTotalTime + " mCount=" + mCount
- + " mAcquireTime=" + mAcquireTime);
+ Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
+ + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
+ + " mAcquireTime=" + mAcquireTimeUs);
}
- if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
+ if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
// If there was no change in the time, then discard this
// count. A somewhat cheezy strategy, but hey.
mCount--;
@@ -2497,32 +2555,32 @@
// Update the total time for all other running Timers with the same type as this Timer
// due to a change in timer count
- private static long refreshTimersLocked(long batteryRealtime,
+ private static long refreshTimersLocked(long batteryRealtimeUs,
final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
- long selfTime = 0;
+ long selfTimeUs = 0;
final int N = pool.size();
for (int i=N-1; i>= 0; i--) {
final StopwatchTimer t = pool.get(i);
- long heldTime = batteryRealtime - t.mUpdateTime;
- if (heldTime > 0) {
- final long myTime = heldTime / N;
+ long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
+ if (heldTimeUs > 0) {
+ final long myTimeUs = heldTimeUs / N;
if (t == self) {
- selfTime = myTime;
+ selfTimeUs = myTimeUs;
}
- t.mTotalTime += myTime;
+ t.mTotalTimeUs += myTimeUs;
}
- t.mUpdateTime = batteryRealtime;
+ t.mUpdateTimeUs = batteryRealtimeUs;
}
- return selfTime;
+ return selfTimeUs;
}
@Override
- protected long computeRunTimeLocked(long curBatteryRealtime) {
- if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
- curBatteryRealtime = mUpdateTime + mTimeout;
+ protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
+ if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
+ curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
}
- return mTotalTime + (mNesting > 0
- ? (curBatteryRealtime - mUpdateTime)
+ return mTotalTimeUs + (mNesting > 0
+ ? (curBatteryRealtimeUs - mUpdateTimeUs)
/ (mTimerPool != null ? mTimerPool.size() : 1)
: 0);
}
@@ -2533,13 +2591,14 @@
}
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
boolean canDetach = mNesting <= 0;
- super.reset(canDetach && detachIfReset);
+ super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
if (mNesting > 0) {
- mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
+ mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
}
- mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
+ // To ensure mCount isn't decreased to -1 if timer is stopped later.
+ mAcquireTimeUs = -1;
return canDetach;
}
@@ -2565,17 +2624,17 @@
* @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
*/
public void setMark(long elapsedRealtimeMs) {
- final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
+ final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
if (mNesting > 0) {
// We are running.
if (mTimerPool != null) {
- refreshTimersLocked(batteryRealtime, mTimerPool, this);
+ refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
} else {
- mTotalTime += batteryRealtime - mUpdateTime;
- mUpdateTime = batteryRealtime;
+ mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
+ mUpdateTimeUs = batteryRealtimeUs;
}
}
- mTimeBeforeMark = mTotalTime;
+ mTimeBeforeMarkUs = mTotalTimeUs;
}
}
@@ -2641,11 +2700,11 @@
}
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
boolean active = false;
// Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
- active |= !mSubTimer.reset(false);
- active |= !super.reset(detachIfReset);
+ active |= !mSubTimer.reset(false, elapsedRealtimeUs);
+ active |= !super.reset(detachIfReset, elapsedRealtimeUs);
return !active;
}
@@ -2682,10 +2741,10 @@
final ArrayMap<String, T> mMap = new ArrayMap<>();
T mCurOverflow;
ArrayMap<String, MutableInt> mActiveOverflow;
- long mLastOverflowTime;
- long mLastOverflowFinishTime;
- long mLastClearTime;
- long mLastCleanupTime;
+ long mLastOverflowTimeMs;
+ long mLastOverflowFinishTimeMs;
+ long mLastClearTimeMs;
+ long mLastCleanupTimeMs;
public OverflowArrayMap(int uid) {
mUid = uid;
@@ -2696,7 +2755,7 @@
}
public void clear() {
- mLastClearTime = SystemClock.elapsedRealtime();
+ mLastClearTimeMs = SystemClock.elapsedRealtime();
mMap.clear();
mCurOverflow = null;
mActiveOverflow = null;
@@ -2712,8 +2771,8 @@
}
}
- public void cleanup() {
- mLastCleanupTime = SystemClock.elapsedRealtime();
+ public void cleanup(long elapsedRealtimeMs) {
+ mLastCleanupTimeMs = elapsedRealtimeMs;
if (mActiveOverflow != null) {
if (mActiveOverflow.size() == 0) {
mActiveOverflow = null;
@@ -2737,7 +2796,7 @@
}
}
- public T startObject(String name) {
+ public T startObject(String name, long elapsedRealtimeMs) {
if (name == null) {
name = "";
}
@@ -2780,7 +2839,7 @@
mActiveOverflow = new ArrayMap<>();
}
mActiveOverflow.put(name, new MutableInt(1));
- mLastOverflowTime = SystemClock.elapsedRealtime();
+ mLastOverflowTimeMs = elapsedRealtimeMs;
return obj;
}
@@ -2790,7 +2849,7 @@
return obj;
}
- public T stopObject(String name) {
+ public T stopObject(String name, long elapsedRealtimeMs) {
if (name == null) {
name = "";
}
@@ -2810,7 +2869,7 @@
over.value--;
if (over.value <= 0) {
mActiveOverflow.remove(name);
- mLastOverflowFinishTime = SystemClock.elapsedRealtime();
+ mLastOverflowFinishTimeMs = elapsedRealtimeMs;
}
return obj;
}
@@ -2830,22 +2889,22 @@
sb.append(mActiveOverflow);
sb.append(" curoverflow=");
sb.append(mCurOverflow);
- long now = SystemClock.elapsedRealtime();
- if (mLastOverflowTime != 0) {
+ long now = elapsedRealtimeMs;
+ if (mLastOverflowTimeMs != 0) {
sb.append(" lastOverflowTime=");
- TimeUtils.formatDuration(mLastOverflowTime-now, sb);
+ TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
}
- if (mLastOverflowFinishTime != 0) {
+ if (mLastOverflowFinishTimeMs != 0) {
sb.append(" lastOverflowFinishTime=");
- TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
+ TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
}
- if (mLastClearTime != 0) {
+ if (mLastClearTimeMs != 0) {
sb.append(" lastClearTime=");
- TimeUtils.formatDuration(mLastClearTime-now, sb);
+ TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
}
- if (mLastCleanupTime != 0) {
+ if (mLastCleanupTimeMs != 0) {
sb.append(" lastCleanupTime=");
- TimeUtils.formatDuration(mLastCleanupTime-now, sb);
+ TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
}
Slog.wtf(TAG, sb.toString());
return null;
@@ -2943,16 +3002,16 @@
mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
}
- public void reset(boolean detachIfReset) {
- mIdleTimeMillis.reset(detachIfReset);
- mScanTimeMillis.reset(detachIfReset);
- mSleepTimeMillis.reset(detachIfReset);
- mRxTimeMillis.reset(detachIfReset);
+ public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
+ mIdleTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
+ mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
+ mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
+ mRxTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
for (LongSamplingCounter counter : mTxTimeMillis) {
- counter.reset(detachIfReset);
+ counter.reset(detachIfReset, elapsedRealtimeUs);
}
- mPowerDrainMaMs.reset(detachIfReset);
- mMonitoredRailChargeConsumedMaMs.reset(detachIfReset);
+ mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
+ mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
}
public void detach() {
@@ -3416,82 +3475,82 @@
final int NU = mUidStats.size();
for (int i=0; i<NU; i++) {
final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.mLastStepUserTime = uid.mCurStepUserTime;
- uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
}
- mLastStepCpuUserTime = mCurStepCpuUserTime;
- mLastStepCpuSystemTime = mCurStepCpuSystemTime;
- mLastStepStatUserTime = mCurStepStatUserTime;
- mLastStepStatSystemTime = mCurStepStatSystemTime;
- mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
- mLastStepStatIrqTime = mCurStepStatIrqTime;
- mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
- mLastStepStatIdleTime = mCurStepStatIdleTime;
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
tmp.clear();
return;
}
if (DEBUG) {
- Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
- + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
- + " irq=" + mLastStepStatIrqTime + " sirq="
- + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
- Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
- + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
- + " irq=" + mCurStepStatIrqTime + " sirq="
- + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
+ + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
+ + " irq=" + mLastStepStatIrqTimeMs + " sirq="
+ + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
+ + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
+ + " irq=" + mCurStepStatIrqTimeMs + " sirq="
+ + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
}
- out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
- out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
- out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
- out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
- out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
- out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
- out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
- out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
+ out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
+ out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
+ out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
+ out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
+ out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
+ out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
+ out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
+ out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
final int NU = mUidStats.size();
for (int i=0; i<NU; i++) {
final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
- final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
- final int totalTime = totalUTime + totalSTime;
- uid.mLastStepUserTime = uid.mCurStepUserTime;
- uid.mLastStepSystemTime = uid.mCurStepSystemTime;
- if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
+ final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
+ final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
+ final int totalTimeMs = totalUTimeMs + totalSTimeMs;
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
+ if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
continue;
}
- if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
+ if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
out.appCpuUid3 = uid.mUid;
- out.appCpuUTime3 = totalUTime;
- out.appCpuSTime3 = totalSTime;
+ out.appCpuUTime3 = totalUTimeMs;
+ out.appCpuSTime3 = totalSTimeMs;
} else {
out.appCpuUid3 = out.appCpuUid2;
out.appCpuUTime3 = out.appCpuUTime2;
out.appCpuSTime3 = out.appCpuSTime2;
- if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
+ if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
out.appCpuUid2 = uid.mUid;
- out.appCpuUTime2 = totalUTime;
- out.appCpuSTime2 = totalSTime;
+ out.appCpuUTime2 = totalUTimeMs;
+ out.appCpuSTime2 = totalSTimeMs;
} else {
out.appCpuUid2 = out.appCpuUid1;
out.appCpuUTime2 = out.appCpuUTime1;
out.appCpuSTime2 = out.appCpuSTime1;
out.appCpuUid1 = uid.mUid;
- out.appCpuUTime1 = totalUTime;
- out.appCpuSTime1 = totalSTime;
+ out.appCpuUTime1 = totalUTimeMs;
+ out.appCpuSTime1 = totalSTimeMs;
}
}
}
- mLastStepCpuUserTime = mCurStepCpuUserTime;
- mLastStepCpuSystemTime = mCurStepCpuSystemTime;
- mLastStepStatUserTime = mCurStepStatUserTime;
- mLastStepStatSystemTime = mCurStepStatSystemTime;
- mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
- mLastStepStatIrqTime = mCurStepStatIrqTime;
- mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
- mLastStepStatIdleTime = mCurStepStatIdleTime;
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
}
public void readHistoryDelta(Parcel src, HistoryItem cur) {
@@ -3631,29 +3690,35 @@
}
public void createFakeHistoryEvents(long numEvents) {
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ final long uptimeMs = mClocks.uptimeMillis();
for(long i = 0; i < numEvents; i++) {
- noteLongPartialWakelockStart("name1", "historyName1", 1000);
- noteLongPartialWakelockFinish("name1", "historyName1", 1000);
+ noteLongPartialWakelockStart("name1", "historyName1", 1000,
+ elapsedRealtimeMs, uptimeMs);
+ noteLongPartialWakelockFinish("name1", "historyName1", 1000,
+ elapsedRealtimeMs, uptimeMs);
}
}
- void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
+ void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
if (!mHaveBatteryLevel || !mRecordingHistory) {
return;
}
- final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
+ final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
- if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
- + Integer.toHexString(diffStates) + " lastDiff="
- + Integer.toHexString(lastDiffStates) + " diff2="
- + Integer.toHexString(diffStates2) + " lastDiff2="
- + Integer.toHexString(lastDiffStates2));
+ if (DEBUG) {
+ Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
+ + Integer.toHexString(diffStates) + " lastDiff="
+ + Integer.toHexString(lastDiffStates) + " diff2="
+ + Integer.toHexString(diffStates2) + " lastDiff2="
+ + Integer.toHexString(lastDiffStates2));
+ }
if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
- && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
+ && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
&& (diffStates2&lastDiffStates2) == 0
&& (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
&& (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
@@ -3674,7 +3739,7 @@
mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
mHistoryBufferLastPos = -1;
- elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
+ elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
// If the last written history had a wakelock tag, we need to retain it.
// Note that the condition above made sure that we aren't in a case where
// both it and the current history item have a wakelock tag.
@@ -3714,11 +3779,9 @@
mHistoryBuffer.setDataPosition(0);
mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
mHistoryBufferLastPos = -1;
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
HistoryItem newItem = new HistoryItem();
newItem.setTo(cur);
- startRecordingHistory(elapsedRealtime, uptime, false);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
return;
}
@@ -3737,11 +3800,11 @@
}
mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
mHistoryLastLastWritten.setTo(mHistoryLastWritten);
- mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
+ mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
mHistoryLastWritten.states &= mActiveHistoryStates;
mHistoryLastWritten.states2 &= mActiveHistoryStates2;
writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
- mLastHistoryElapsedRealtime = elapsedRealtimeMs;
+ mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
cur.wakelockTag = null;
cur.wakeReasonTag = null;
cur.eventCode = HistoryItem.EVENT_NONE;
@@ -3755,27 +3818,27 @@
int mChangedStates2 = 0;
void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
- if (mTrackRunningHistoryElapsedRealtime != 0) {
- final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
- final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
- if (diffUptime < (diffElapsed-20)) {
- final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
+ if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
+ final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
+ final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
+ if (diffUptimeMs < (diffElapsedMs - 20)) {
+ final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
mHistoryAddTmp.setTo(mHistoryLastWritten);
mHistoryAddTmp.wakelockTag = null;
mHistoryAddTmp.wakeReasonTag = null;
mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
- addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
+ addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
}
}
mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
- mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
- mTrackRunningHistoryUptime = uptimeMs;
- addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
+ mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ mTrackRunningHistoryUptimeMs = uptimeMs;
+ addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
}
- void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
- addHistoryBufferLocked(elapsedRealtimeMs, cur);
+ void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
if (!USE_OLD_HISTORY) {
return;
@@ -3790,13 +3853,13 @@
// are now resetting back to their original value, then just collapse
// into one record.
if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
- && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
+ && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 1000)
&& ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
&& ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
// If the current is the same as the one before, then we no
// longer need the entry.
if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
- && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
+ && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 500)
&& mHistoryLastEnd.sameNonEvent(cur)) {
mHistoryLastEnd.next = null;
mHistoryEnd.next = mHistoryCache;
@@ -3832,7 +3895,7 @@
} else {
rec = new HistoryItem();
}
- rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
+ rec.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
addHistoryRecordLocked(rec);
}
@@ -3860,10 +3923,10 @@
mNumHistoryItems = 0;
}
- mHistoryBaseTime = 0;
- mLastHistoryElapsedRealtime = 0;
- mTrackRunningHistoryElapsedRealtime = 0;
- mTrackRunningHistoryUptime = 0;
+ mHistoryBaseTimeMs = 0;
+ mLastHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryUptimeMs = 0;
mHistoryBuffer.setDataSize(0);
mHistoryBuffer.setDataPosition(0);
@@ -3879,8 +3942,8 @@
}
@GuardedBy("this")
- public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
- long realtime) {
+ public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
+ long realtimeUs) {
final boolean screenOff = !isScreenOn(screenState);
final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
final boolean updateOnBatteryScreenOffTimeBase =
@@ -3888,14 +3951,15 @@
if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
if (updateOnBatteryScreenOffTimeBase) {
- updateKernelWakelocksLocked();
+ updateKernelWakelocksLocked(realtimeUs);
updateBatteryPropertiesLocked();
}
// This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
// updateRpmStatsLocked is too slow to run each screen change. When the speed is
// improved, remove the surrounding if{}.
if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
- updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
+ // if either OnBattery or OnBatteryScreenOfftimebase changes.
+ updateRpmStatsLocked(realtimeUs);
}
if (DEBUG_ENERGY_CPU) {
Slog.d(TAG, "Updating cpu time because screen is now "
@@ -3903,16 +3967,17 @@
+ " and battery is " + (unplugged ? "on" : "off"));
}
- mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
+ mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
if (updateOnBatteryTimeBase) {
for (int i = mUidStats.size() - 1; i >= 0; --i) {
- mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
+ mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
}
}
if (updateOnBatteryScreenOffTimeBase) {
- mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
+ mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
+ uptimeUs, realtimeUs);
for (int i = mUidStats.size() - 1; i >= 0; --i) {
- mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
+ mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
}
}
}
@@ -3931,8 +3996,14 @@
}
public void addIsolatedUidLocked(int isolatedUid, int appUid) {
+ addIsolatedUidLocked(isolatedUid, appUid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void addIsolatedUidLocked(int isolatedUid, int appUid,
+ long elapsedRealtimeMs, long uptimeMs) {
mIsolatedUids.put(isolatedUid, appUid);
- final Uid u = getUidStatsLocked(appUid);
+ final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs);
u.addIsolatedUid(isolatedUid);
}
@@ -3955,14 +4026,22 @@
*/
@GuardedBy("this")
public void removeIsolatedUidLocked(int isolatedUid) {
+ removeIsolatedUidLocked(isolatedUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see #removeIsolatedUidLocked(int)
+ */
+ @GuardedBy("this")
+ public void removeIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) {
final int idx = mIsolatedUids.indexOfKey(isolatedUid);
if (idx >= 0) {
final int ownerUid = mIsolatedUids.valueAt(idx);
- final Uid u = getUidStatsLocked(ownerUid);
+ final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs);
u.removeIsolatedUid(isolatedUid);
mIsolatedUids.removeAt(idx);
}
- mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
+ mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs));
}
public int mapUid(int uid) {
@@ -3971,26 +4050,39 @@
}
public void noteEventLocked(int code, String name, int uid) {
+ noteEventLocked(code, name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteEventLocked(int code, String name, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (!mActiveEvents.updateState(code, name, uid, 0)) {
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
public void noteCurrentTimeChangedLocked() {
final long currentTime = System.currentTimeMillis();
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
- recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
+ noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
+ }
+
+ public void noteCurrentTimeChangedLocked(long currentTimeMs,
+ long elapsedRealtimeMs, long uptimeMs) {
+ recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
}
public void noteProcessStartLocked(String name, int uid) {
+ noteProcessStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteProcessStartLocked(String name, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (isOnBattery()) {
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
u.getProcessStatsLocked(name).incStartsLocked();
}
if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
@@ -3999,28 +4091,40 @@
if (!mRecordAllHistory) {
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
}
public void noteProcessCrashLocked(String name, int uid) {
+ noteProcessCrashLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteProcessCrashLocked(String name, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (isOnBattery()) {
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
u.getProcessStatsLocked(name).incNumCrashesLocked();
}
}
public void noteProcessAnrLocked(String name, int uid) {
+ noteProcessAnrLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (isOnBattery()) {
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
u.getProcessStatsLocked(name).incNumAnrsLocked();
}
}
public void noteUidProcessStateLocked(int uid, int state) {
+ noteUidProcessStateLocked(uid, state, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteUidProcessStateLocked(int uid, int state,
+ long elapsedRealtimeMs, long uptimeMs) {
int parentUid = mapUid(uid);
if (uid != parentUid) {
// Isolated UIDs process state is already rolled up into parent, so no need to track
@@ -4032,10 +4136,16 @@
// and isolated uids rather than only the parent uid.
FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
ActivityManager.processStateAmToProto(state));
- getUidStatsLocked(uid).updateUidProcessStateLocked(state);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
}
public void noteProcessFinishLocked(String name, int uid) {
+ noteProcessFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteProcessFinishLocked(String name, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
return;
@@ -4043,82 +4153,120 @@
if (!mRecordAllHistory) {
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
+ name, uid);
}
public void noteSyncStartLocked(String name, int uid) {
+ noteSyncStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStartSyncLocked(name, elapsedRealtimeMs);
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
}
public void noteSyncFinishLocked(String name, int uid) {
+ noteSyncFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStopSyncLocked(name, elapsedRealtimeMs);
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
+ name, uid);
}
public void noteJobStartLocked(String name, int uid) {
+ noteJobStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStartJobLocked(name, elapsedRealtimeMs);
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
}
public void noteJobFinishLocked(String name, int uid, int stopReason) {
+ noteJobFinishLocked(name, uid, stopReason,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteJobFinishLocked(String name, int uid, int stopReason,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
}
public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
+ noteJobsDeferredLocked(uid, numDeferred, sinceLast,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteJobsDeferredLocked(numDeferred, sinceLast);
}
public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
- noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
+ noteAlarmStartLocked(name, workSource, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
+ noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
+ elapsedRealtimeMs, uptimeMs);
}
public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
- noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
+ noteAlarmFinishLocked(name, workSource, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
+ noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
+ elapsedRealtimeMs, uptimeMs);
}
private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
int uid) {
+ noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
+ int uid, long elapsedRealtimeMs, long uptimeMs) {
if (!mRecordAllHistory) {
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
-
if (workSource != null) {
for (int i = 0; i < workSource.size(); ++i) {
uid = mapUid(workSource.getUid(i));
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
@@ -4127,7 +4275,7 @@
for (int i = 0; i < workChains.size(); ++i) {
uid = mapUid(workChains.get(i).getAttributionUid());
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4135,13 +4283,19 @@
uid = mapUid(uid);
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
String tag) {
+ noteWakupAlarmLocked(packageName, uid, workSource, tag,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
+ String tag, long elapsedRealtimeMs, long uptimeMs) {
if (workSource != null) {
for (int i = 0; i < workSource.size(); ++i) {
uid = workSource.getUid(i);
@@ -4149,7 +4303,8 @@
if (isOnBattery()) {
BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
- workSourceName != null ? workSourceName : packageName);
+ workSourceName != null ? workSourceName : packageName,
+ elapsedRealtimeMs, uptimeMs);
pkg.noteWakeupAlarmLocked(tag);
}
}
@@ -4161,14 +4316,16 @@
uid = wc.getAttributionUid();
if (isOnBattery()) {
- BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
+ BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
+ elapsedRealtimeMs, uptimeMs);
pkg.noteWakeupAlarmLocked(tag);
}
}
}
} else {
if (isOnBattery()) {
- BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
+ BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
+ elapsedRealtimeMs, uptimeMs);
pkg.noteWakeupAlarmLocked(tag);
}
}
@@ -4228,7 +4385,8 @@
public void setPretendScreenOff(boolean pretendScreenOff) {
if (mPretendScreenOff != pretendScreenOff) {
mPretendScreenOff = pretendScreenOff;
- noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
+ noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
}
}
@@ -4236,19 +4394,25 @@
private int mInitialAcquireWakeUid = -1;
public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
- int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
+ int type, boolean unimportantForLogging) {
+ noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
+ int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (type == WAKE_TYPE_PARTIAL) {
// Only care about partial wake locks, since full wake locks
// will be canceled when the user puts the screen to sleep.
- aggregateLastWakeupUptimeLocked(uptime);
+ aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
if (historyName == null) {
historyName = name;
}
if (mRecordAllHistory) {
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
uid, 0)) {
- addHistoryEventLocked(elapsedRealtime, uptime,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
}
}
@@ -4260,7 +4424,7 @@
mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
mWakeLockImportant = !unimportantForLogging;
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
} else if (!mWakeLockImportant && !unimportantForLogging
&& mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
if (mHistoryLastWritten.wakelockTag != null) {
@@ -4269,7 +4433,7 @@
mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mWakeLockImportant = true;
}
@@ -4285,7 +4449,8 @@
requestWakelockCpuUpdate();
}
- getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
if (wc != null) {
FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
@@ -4300,7 +4465,13 @@
}
public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
- int type, long elapsedRealtime, long uptime) {
+ int type) {
+ noteStopWakeLocked(uid, pid, wc, name, historyName, type,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
+ int type, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (type == WAKE_TYPE_PARTIAL) {
mWakeLockNesting--;
@@ -4310,7 +4481,7 @@
}
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
uid, 0)) {
- addHistoryEventLocked(elapsedRealtime, uptime,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
}
}
@@ -4320,7 +4491,7 @@
+ Integer.toHexString(mHistoryCur.states));
mInitialAcquireWakeName = null;
mInitialAcquireWakeUid = -1;
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
if (uid >= 0) {
@@ -4331,7 +4502,8 @@
requestWakelockCpuUpdate();
}
- getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
if (wc != null) {
FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
wc.getTags(), getPowerManagerWakeLockLevel(type), name,
@@ -4377,12 +4549,17 @@
public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, boolean unimportantForLogging) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
+ String historyName, int type, boolean unimportantForLogging,
+ long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
for (int i=0; i<N; i++) {
noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
- unimportantForLogging, elapsedRealtime, uptime);
+ unimportantForLogging, elapsedRealtimeMs, uptimeMs);
}
List<WorkChain> wcs = ws.getWorkChains();
@@ -4390,7 +4567,7 @@
for (int i = 0; i < wcs.size(); ++i) {
final WorkChain wc = wcs.get(i);
noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
- unimportantForLogging, elapsedRealtime, uptime);
+ unimportantForLogging, elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -4398,9 +4575,15 @@
public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, WorkSource newWs, int newPid, String newName,
String newHistoryName, int newType, boolean newUnimportantForLogging) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, newWs, newPid,
+ newName, newHistoryName, newType, newUnimportantForLogging,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+ public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
+ String historyName, int type, WorkSource newWs, int newPid, String newName,
+ String newHistoryName, int newType, boolean newUnimportantForLogging,
+ long elapsedRealtimeMs, long uptimeMs) {
List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
// For correct semantics, we start the need worksources first, so that we won't
@@ -4411,7 +4594,7 @@
final int NN = newWs.size();
for (int i=0; i<NN; i++) {
noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
- newUnimportantForLogging, elapsedRealtime, uptime);
+ newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
}
if (wcs != null) {
List<WorkChain> newChains = wcs[0];
@@ -4419,8 +4602,8 @@
for (int i = 0; i < newChains.size(); ++i) {
final WorkChain newChain = newChains.get(i);
noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
- newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
- uptime);
+ newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
+ uptimeMs);
}
}
}
@@ -4428,8 +4611,8 @@
// Then the stops :
final int NO = ws.size();
for (int i=0; i<NO; i++) {
- noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
- uptime);
+ noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
+ uptimeMs);
}
if (wcs != null) {
List<WorkChain> goneChains = wcs[1];
@@ -4437,7 +4620,7 @@
for (int i = 0; i < goneChains.size(); ++i) {
final WorkChain goneChain = goneChains.get(i);
noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
- historyName, type, elapsedRealtime, uptime);
+ historyName, type, elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -4445,12 +4628,16 @@
public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
+ String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
for (int i=0; i<N; i++) {
- noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
- uptime);
+ noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
+ uptimeMs);
}
List<WorkChain> wcs = ws.getWorkChains();
@@ -4458,22 +4645,35 @@
for (int i = 0; i < wcs.size(); ++i) {
final WorkChain wc = wcs.get(i);
noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
- elapsedRealtime, uptime);
+ elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
+ noteLongPartialWakelockStart(name, historyName, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteLongPartialWakelockStart(String name, String historyName, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- noteLongPartialWakeLockStartInternal(name, historyName, uid);
+ noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
}
public void noteLongPartialWakelockStartFromSource(String name, String historyName,
WorkSource workSource) {
+ noteLongPartialWakelockStartFromSource(name, historyName, workSource,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteLongPartialWakelockStartFromSource(String name, String historyName,
+ WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
final int N = workSource.size();
for (int i = 0; i < N; ++i) {
final int uid = mapUid(workSource.getUid(i));
- noteLongPartialWakeLockStartInternal(name, historyName, uid);
+ noteLongPartialWakeLockStartInternal(name, historyName, uid,
+ elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = workSource.getWorkChains();
@@ -4481,14 +4681,14 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = workChain.getAttributionUid();
- noteLongPartialWakeLockStartInternal(name, historyName, uid);
+ noteLongPartialWakeLockStartInternal(name, historyName, uid,
+ elapsedRealtimeMs, uptimeMs);
}
}
}
- private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
if (historyName == null) {
historyName = name;
}
@@ -4496,21 +4696,34 @@
0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
historyName, uid);
}
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
+ noteLongPartialWakelockFinish(name, historyName, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
}
public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
WorkSource workSource) {
+ noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
+ WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
final int N = workSource.size();
for (int i = 0; i < N; ++i) {
final int uid = mapUid(workSource.getUid(i));
- noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid,
+ elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = workSource.getWorkChains();
@@ -4518,14 +4731,14 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = workChain.getAttributionUid();
- noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid,
+ elapsedRealtimeMs, uptimeMs);
}
}
}
- private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
if (historyName == null) {
historyName = name;
}
@@ -4533,33 +4746,35 @@
0)) {
return;
}
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
historyName, uid);
}
- void aggregateLastWakeupUptimeLocked(long uptimeMs) {
+ void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mLastWakeupReason != null) {
- long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
+ long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
- timer.add(deltaUptime * 1000, 1); // time in in microseconds
+ timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
- /* duration_usec */ deltaUptime * 1000);
+ /* duration_usec */ deltaUptimeMs * 1000);
mLastWakeupReason = null;
}
}
public void noteWakeupReasonLocked(String reason) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteWakeupReasonLocked(reason, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
+ Integer.toHexString(mHistoryCur.states));
- aggregateLastWakeupUptimeLocked(uptime);
+ aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
mHistoryCur.wakeReasonTag.string = reason;
mHistoryCur.wakeReasonTag.uid = 0;
mLastWakeupReason = reason;
- mLastWakeupUptimeMs = uptime;
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ mLastWakeupUptimeMs = uptimeMs;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
public boolean startAddingCpuLocked() {
@@ -4567,21 +4782,23 @@
return mOnBatteryInternal;
}
- public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
- int statSystemTime, int statIOWaitTime, int statIrqTime,
- int statSoftIrqTime, int statIdleTime) {
- if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
- + " user=" + statUserTime + " sys=" + statSystemTime
- + " io=" + statIOWaitTime + " irq=" + statIrqTime
- + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
- mCurStepCpuUserTime += totalUTime;
- mCurStepCpuSystemTime += totalSTime;
- mCurStepStatUserTime += statUserTime;
- mCurStepStatSystemTime += statSystemTime;
- mCurStepStatIOWaitTime += statIOWaitTime;
- mCurStepStatIrqTime += statIrqTime;
- mCurStepStatSoftIrqTime += statSoftIrqTime;
- mCurStepStatIdleTime += statIdleTime;
+ public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
+ int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
+ int statSoftIrqTimeMs, int statIdleTimeMs) {
+ if (DEBUG) {
+ Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
+ + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
+ + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
+ + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
+ }
+ mCurStepCpuUserTimeMs += totalUTimeMs;
+ mCurStepCpuSystemTimeMs += totalSTimeMs;
+ mCurStepStatUserTimeMs += statUserTimeMs;
+ mCurStepStatSystemTimeMs += statSystemTimeMs;
+ mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
+ mCurStepStatIrqTimeMs += statIrqTimeMs;
+ mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
+ mCurStepStatIdleTimeMs += statIdleTimeMs;
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -4592,65 +4809,76 @@
}
}
- public long getProcessWakeTime(int uid, int pid, long realtime) {
+ public long getProcessWakeTime(int uid, int pid, long realtimeMs) {
uid = mapUid(uid);
Uid u = mUidStats.get(uid);
if (u != null) {
Uid.Pid p = u.mPids.get(pid);
if (p != null) {
- return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
+ return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtimeMs - p.mWakeStartMs) : 0);
}
}
return 0;
}
- public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
+ public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
uid = mapUid(uid);
Uid u = mUidStats.get(uid);
if (u != null) {
- u.reportExcessiveCpuLocked(proc, overTime, usedTime);
+ u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
}
}
int mSensorNesting;
public void noteStartSensorLocked(int uid, int sensor) {
+ noteStartSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mSensorNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mSensorNesting++;
- getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStartSensor(sensor, elapsedRealtimeMs);
}
public void noteStopSensorLocked(int uid, int sensor) {
+ noteStopSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mSensorNesting--;
if (mSensorNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
- getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteStopSensor(sensor, elapsedRealtimeMs);
}
int mGpsNesting;
public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
+ noteGpsChangedLocked(oldWs, newWs, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
+ long elapsedRealtimeMs, long uptimeMs) {
for (int i = 0; i < newWs.size(); ++i) {
- noteStartGpsLocked(newWs.getUid(i), null);
+ noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
}
for (int i = 0; i < oldWs.size(); ++i) {
- noteStopGpsLocked((oldWs.getUid(i)), null);
+ noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
}
List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
@@ -4658,28 +4886,27 @@
if (wcs[0] != null) {
final List<WorkChain> newChains = wcs[0];
for (int i = 0; i < newChains.size(); ++i) {
- noteStartGpsLocked(-1, newChains.get(i));
+ noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
}
}
if (wcs[1] != null) {
final List<WorkChain> goneChains = wcs[1];
for (int i = 0; i < goneChains.size(); ++i) {
- noteStopGpsLocked(-1, goneChains.get(i));
+ noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
}
}
}
}
- private void noteStartGpsLocked(int uid, WorkChain workChain) {
+ private void noteStartGpsLocked(int uid, WorkChain workChain,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mGpsNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mGpsNesting++;
@@ -4692,20 +4919,19 @@
FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
}
- getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
}
- private void noteStopGpsLocked(int uid, WorkChain workChain) {
+ private void noteStopGpsLocked(int uid, WorkChain workChain,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mGpsNesting--;
if (mGpsNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- stopAllGpsSignalQualityTimersLocked(-1);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
mGpsSignalQualityBin = -1;
}
@@ -4717,29 +4943,31 @@
workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
}
- getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
}
public void noteGpsSignalQualityLocked(int signalLevel) {
+ noteGpsSignalQualityLocked(signalLevel, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
if (mGpsNesting == 0) {
return;
}
if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
- stopAllGpsSignalQualityTimersLocked(-1);
+ stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mGpsSignalQualityBin != signalLevel) {
if (mGpsSignalQualityBin >= 0) {
- mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
+ mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
}
if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
- mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
+ mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
}
mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
| (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGpsSignalQualityBin = signalLevel;
}
return;
@@ -4747,6 +4975,13 @@
@GuardedBy("this")
public void noteScreenStateLocked(int state) {
+ noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
+ System.currentTimeMillis());
+ }
+
+ @GuardedBy("this")
+ public void noteScreenStateLocked(int state,
+ long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
state = mPretendScreenOff ? Display.STATE_OFF : state;
// Battery stats relies on there being 4 states. To accommodate this, new states beyond the
@@ -4763,7 +4998,7 @@
}
if (mScreenState != state) {
- recordDailyStatsIfNeededLocked(true);
+ recordDailyStatsIfNeededLocked(true, currentTimeMs);
final int oldState = mScreenState;
mScreenState = state;
if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
@@ -4779,56 +5014,55 @@
}
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
-
boolean updateHistory = false;
if (isScreenDoze(state) && !isScreenDoze(oldState)) {
mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
- mScreenDozeTimer.startRunningLocked(elapsedRealtime);
+ mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
updateHistory = true;
} else if (isScreenDoze(oldState) && !isScreenDoze(state)) {
mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
- mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
+ mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
updateHistory = true;
}
if (isScreenOn(state)) {
mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
+ Integer.toHexString(mHistoryCur.states));
- mScreenOnTimer.startRunningLocked(elapsedRealtime);
+ mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
- mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
+ mScreenBrightnessTimer[mScreenBrightnessBin]
+ .startRunningLocked(elapsedRealtimeMs);
}
updateHistory = true;
} else if (isScreenOn(oldState)) {
mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
+ Integer.toHexString(mHistoryCur.states));
- mScreenOnTimer.stopRunningLocked(elapsedRealtime);
+ mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
- mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
+ mScreenBrightnessTimer[mScreenBrightnessBin]
+ .stopRunningLocked(elapsedRealtimeMs);
}
updateHistory = true;
}
if (updateHistory) {
if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
+ Display.stateToString(state));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mExternalSync.scheduleCpuSyncDueToScreenStateChange(
mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
if (isScreenOn(state)) {
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
- mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ uptimeMs * 1000, elapsedRealtimeMs * 1000);
// Fake a wake lock, so we consider the device waked as long as the screen is on.
noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
- elapsedRealtime, uptime);
+ elapsedRealtimeMs, uptimeMs);
} else if (isScreenOn(oldState)) {
noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
- elapsedRealtime, uptime);
+ elapsedRealtimeMs, uptimeMs);
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
- mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ uptimeMs * 1000, elapsedRealtimeMs * 1000);
}
// Update discharge amounts.
if (mOnBatteryInternal) {
@@ -4839,23 +5073,27 @@
@UnsupportedAppUsage
public void noteScreenBrightnessLocked(int brightness) {
+ noteScreenBrightnessLocked(brightness, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteScreenBrightnessLocked(int brightness, long elapsedRealtimeMs, long uptimeMs) {
// Bin the brightness.
int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
if (bin < 0) bin = 0;
else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
if (mScreenBrightnessBin != bin) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
| (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
if (mScreenState == Display.STATE_ON) {
if (mScreenBrightnessBin >= 0) {
- mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
+ mScreenBrightnessTimer[mScreenBrightnessBin]
+ .stopRunningLocked(elapsedRealtimeMs);
}
- mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
+ mScreenBrightnessTimer[bin]
+ .startRunningLocked(elapsedRealtimeMs);
}
mScreenBrightnessBin = bin;
}
@@ -4863,36 +5101,50 @@
@UnsupportedAppUsage
public void noteUserActivityLocked(int uid, int event) {
+ noteUserActivityLocked(uid, event, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
if (mOnBatteryInternal) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteUserActivityLocked(event);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
}
}
public void noteWakeUpLocked(String reason, int reasonUid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
+ noteWakeUpLocked(reason, reasonUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWakeUpLocked(String reason, int reasonUid,
+ long elapsedRealtimeMs, long uptimeMs) {
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
reason, reasonUid);
}
public void noteInteractiveLocked(boolean interactive) {
+ noteInteractiveLocked(interactive, mClocks.elapsedRealtime());
+ }
+
+ public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
if (mInteractive != interactive) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
mInteractive = interactive;
if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
if (interactive) {
- mInteractiveTimer.startRunningLocked(elapsedRealtime);
+ mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mInteractiveTimer.stopRunningLocked(elapsedRealtime);
+ mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
}
public void noteConnectivityChangedLocked(int type, String extra) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
+ noteConnectivityChangedLocked(type, extra,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteConnectivityChangedLocked(int type, String extra,
+ long elapsedRealtimeMs, long uptimeMs) {
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
extra, type);
mNumConnectivityChange++;
}
@@ -4902,15 +5154,19 @@
uid = mapUid(uid);
addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
- getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
+ getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
}
/**
* Updates the radio power state and returns true if an external stats collection should occur.
*/
public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
if (mMobileRadioPowerState != powerState) {
long realElapsedRealtimeMs;
final boolean active =
@@ -4918,31 +5174,31 @@
|| powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
if (active) {
if (uid > 0) {
- noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
+ noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
}
- mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
+ mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
} else {
realElapsedRealtimeMs = timestampNs / (1000*1000);
- long lastUpdateTimeMs = mMobileRadioActiveStartTime;
+ long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
if (realElapsedRealtimeMs < lastUpdateTimeMs) {
Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
+ " is before start time " + lastUpdateTimeMs);
- realElapsedRealtimeMs = elapsedRealtime;
- } else if (realElapsedRealtimeMs < elapsedRealtime) {
- mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
+ realElapsedRealtimeMs = elapsedRealtimeMs;
+ } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
+ mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
- realElapsedRealtimeMs);
}
mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
}
if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mMobileRadioPowerState = powerState;
if (active) {
- mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
- mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
+ mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
+ mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
} else {
mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
@@ -4954,25 +5210,27 @@
}
public void notePowerSaveModeLocked(boolean enabled) {
+ notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
if (mPowerSaveModeEnabled != enabled) {
int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mPowerSaveModeEnabled = enabled;
if (enabled) {
mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
+ Integer.toHexString(mHistoryCur.states2));
- mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
+ mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
} else {
mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
+ Integer.toHexString(mHistoryCur.states2));
- mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
+ mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
}
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
enabled
? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
@@ -4981,8 +5239,12 @@
}
public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteDeviceIdleModeLocked(mode, activeReason, activeUid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
+ long elapsedRealtimeMs, long uptimeMs) {
boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
if (mDeviceIdling && !nowIdling && activeReason == null) {
// We don't go out of general idling mode until explicitly taken out of
@@ -4996,7 +5258,7 @@
nowLightIdling = true;
}
if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
activeReason, activeUid);
}
if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
@@ -5012,17 +5274,17 @@
mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
if (nowIdling) {
- mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
+ mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
+ mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
if (mDeviceLightIdling != nowLightIdling) {
mDeviceLightIdling = nowLightIdling;
if (nowLightIdling) {
- mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
+ mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
+ mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
if (mDeviceIdleMode != mode) {
@@ -5030,24 +5292,24 @@
| (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- long lastDuration = elapsedRealtime - mLastIdleTimeStart;
- mLastIdleTimeStart = elapsedRealtime;
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
+ mLastIdleTimeStartMs = elapsedRealtimeMs;
if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
- if (lastDuration > mLongestLightIdleTime) {
- mLongestLightIdleTime = lastDuration;
+ if (lastDuration > mLongestLightIdleTimeMs) {
+ mLongestLightIdleTimeMs = lastDuration;
}
- mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
+ mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
} else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
- if (lastDuration > mLongestFullIdleTime) {
- mLongestFullIdleTime = lastDuration;
+ if (lastDuration > mLongestFullIdleTimeMs) {
+ mLongestFullIdleTimeMs = lastDuration;
}
- mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
+ mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
}
if (mode == DEVICE_IDLE_MODE_LIGHT) {
- mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
+ mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
} else if (mode == DEVICE_IDLE_MODE_DEEP) {
- mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
+ mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
}
mDeviceIdleMode = mode;
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
@@ -5055,10 +5317,14 @@
}
public void notePackageInstalledLocked(String pkgName, long versionCode) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ notePackageInstalledLocked(pkgName, versionCode,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePackageInstalledLocked(String pkgName, long versionCode,
+ long elapsedRealtimeMs, long uptimeMs) {
// XXX need to figure out what to do with long version codes.
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
pkgName, (int)versionCode);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
@@ -5068,10 +5334,13 @@
}
public void notePackageUninstalledLocked(String pkgName) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
- pkgName, 0);
+ notePackageUninstalledLocked(pkgName, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePackageUninstalledLocked(String pkgName,
+ long elapsedRealtimeMs, long uptimeMs) {
+ addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
pc.mUpdate = true;
@@ -5086,42 +5355,49 @@
}
void stopAllGpsSignalQualityTimersLocked(int except) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
+ stopAllGpsSignalQualityTimersLocked(except, mClocks.elapsedRealtime());
+ }
+
+ void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
if (i == except) {
continue;
}
while (mGpsSignalQualityTimer[i].isRunningLocked()) {
- mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
+ mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
}
}
}
@UnsupportedAppUsage
public void notePhoneOnLocked() {
+ notePhoneOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mPhoneOn) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = true;
- mPhoneOnTimer.startRunningLocked(elapsedRealtime);
+ mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
}
}
@UnsupportedAppUsage
public void notePhoneOffLocked() {
+ notePhoneOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mPhoneOn) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = false;
- mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
+ mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
@@ -5133,7 +5409,8 @@
public void onReceive(Context context, Intent intent) {
final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
synchronized (BatteryStatsImpl.this) {
- noteUsbConnectionStateLocked(state);
+ noteUsbConnectionStateLocked(state, mClocks.elapsedRealtime(),
+ mClocks.uptimeMillis());
}
}
}, usbStateFilter);
@@ -5142,12 +5419,14 @@
final Intent usbState = context.registerReceiver(null, usbStateFilter);
final boolean initState = usbState != null && usbState.getBooleanExtra(
UsbManager.USB_CONNECTED, false);
- noteUsbConnectionStateLocked(initState);
+ noteUsbConnectionStateLocked(initState, mClocks.elapsedRealtime(),
+ mClocks.uptimeMillis());
}
}
}
- private void noteUsbConnectionStateLocked(boolean connected) {
+ private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
+ long uptimeMs) {
int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
if (mUsbDataState != newState) {
mUsbDataState = newState;
@@ -5156,18 +5435,17 @@
} else {
mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
}
- addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
- void stopAllPhoneSignalStrengthTimersLocked(int except) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
+ void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
if (i == except) {
continue;
}
while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
- mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
+ mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
}
}
}
@@ -5185,7 +5463,8 @@
return state;
}
- private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
+ private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
+ long elapsedRealtimeMs, long uptimeMs) {
boolean scanning = false;
boolean newHistory = false;
@@ -5193,9 +5472,6 @@
mPhoneSimStateRaw = simState;
mPhoneSignalStrengthBinRaw = strengthBin;
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
-
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
// In this case we will always be STATE_OUT_OF_SERVICE, so need
// to infer that we are scanning from other data.
@@ -5223,7 +5499,7 @@
newHistory = true;
if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
+ Integer.toHexString(mHistoryCur.states));
- mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
+ mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
simState, strengthBin);
}
@@ -5236,7 +5512,7 @@
if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
+ Integer.toHexString(mHistoryCur.states));
newHistory = true;
- mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
+ mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
simState, strengthBin);
}
@@ -5254,13 +5530,14 @@
if (mPhoneSignalStrengthBin != strengthBin) {
if (mPhoneSignalStrengthBin >= 0) {
mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
- elapsedRealtime);
+ elapsedRealtimeMs);
}
if (strengthBin >= 0) {
if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
- mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
+ mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
+ mHistoryCur.states =
+ (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
| (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -5268,13 +5545,13 @@
FrameworkStatsLog.write(
FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
} else {
- stopAllPhoneSignalStrengthTimersLocked(-1);
+ stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
}
mPhoneSignalStrengthBin = strengthBin;
}
if (newHistory) {
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -5283,18 +5560,37 @@
* @param state phone state from ServiceState.getState()
*/
public void notePhoneStateLocked(int state, int simState) {
- updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
+ notePhoneStateLocked(state, simState, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePhoneStateLocked(int state, int simState,
+ long elapsedRealtimeMs, long uptimeMs) {
+ updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
+ elapsedRealtimeMs, uptimeMs);
}
@UnsupportedAppUsage
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
+ notePhoneSignalStrengthLocked(signalStrength,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
+ long elapsedRealtimeMs, long uptimeMs) {
// Bin the strength.
int bin = signalStrength.getLevel();
- updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
+ updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin,
+ elapsedRealtimeMs, uptimeMs);
}
@UnsupportedAppUsage
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
+ notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
+ long elapsedRealtimeMs, long uptimeMs) {
// BatteryStats uses 0 to represent no network type.
// Telephony does not have a concept of no network type, and uses 0 to represent unknown.
// Unknown is included in DATA_CONNECTION_OTHER.
@@ -5318,312 +5614,374 @@
}
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
| (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
if (mPhoneDataConnectionType >= 0) {
mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
- elapsedRealtime);
+ elapsedRealtimeMs);
}
mPhoneDataConnectionType = bin;
- mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
+ mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
}
}
public void noteWifiOnLocked() {
+ noteWifiOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mWifiOn) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiOn = true;
- mWifiOnTimer.startRunningLocked(elapsedRealtime);
+ mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
}
}
public void noteWifiOffLocked() {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteWifiOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mWifiOn) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiOn = false;
- mWifiOnTimer.stopRunningLocked(elapsedRealtime);
+ mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
}
}
@UnsupportedAppUsage
public void noteAudioOnLocked(int uid) {
+ noteAudioOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mAudioOnNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mAudioOnTimer.startRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mAudioOnNesting++;
- getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteAudioTurnedOnLocked(elapsedRealtimeMs);
}
@UnsupportedAppUsage
public void noteAudioOffLocked(int uid) {
+ noteAudioOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting == 0) {
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (--mAudioOnNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mAudioOnTimer.stopRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteAudioTurnedOffLocked(elapsedRealtimeMs);
}
@UnsupportedAppUsage
public void noteVideoOnLocked(int uid) {
+ noteVideoOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mVideoOnNesting == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mVideoOnTimer.startRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mVideoOnNesting++;
- getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteVideoTurnedOnLocked(elapsedRealtimeMs);
}
@UnsupportedAppUsage
public void noteVideoOffLocked(int uid) {
+ noteVideoOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting == 0) {
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (--mVideoOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mVideoOnTimer.stopRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteVideoTurnedOffLocked(elapsedRealtimeMs);
}
public void noteResetAudioLocked() {
+ noteResetAudioLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting > 0) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mAudioOnNesting = 0;
mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.noteResetAudioLocked(elapsedRealtime);
+ uid.noteResetAudioLocked(elapsedRealtimeMs);
}
}
}
public void noteResetVideoLocked() {
+ noteResetVideoLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting > 0) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mVideoOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.noteResetVideoLocked(elapsedRealtime);
+ uid.noteResetVideoLocked(elapsedRealtimeMs);
}
}
}
public void noteActivityResumedLocked(int uid) {
+ noteActivityResumedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteActivityResumedLocked(elapsedRealtimeMs);
}
public void noteActivityPausedLocked(int uid) {
+ noteActivityPausedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteActivityPausedLocked(elapsedRealtimeMs);
}
public void noteVibratorOnLocked(int uid, long durationMillis) {
+ noteVibratorOnLocked(uid, durationMillis,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteVibratorOnLocked(int uid, long durationMillis,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
}
public void noteVibratorOffLocked(int uid) {
+ noteVibratorOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteVibratorOffLocked();
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteVibratorOffLocked(elapsedRealtimeMs);
}
public void noteFlashlightOnLocked(int uid) {
+ noteFlashlightOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mFlashlightOnNesting++ == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
}
public void noteFlashlightOffLocked(int uid) {
+ noteFlashlightOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting == 0) {
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (--mFlashlightOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
}
public void noteCameraOnLocked(int uid) {
+ noteCameraOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mCameraOnNesting++ == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mCameraOnTimer.startRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteCameraTurnedOnLocked(elapsedRealtimeMs);
}
public void noteCameraOffLocked(int uid) {
+ noteCameraOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting == 0) {
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (--mCameraOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mCameraOnTimer.stopRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteCameraTurnedOffLocked(elapsedRealtimeMs);
}
public void noteResetCameraLocked() {
+ noteResetCameraLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting > 0) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mCameraOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.noteResetCameraLocked(elapsedRealtime);
+ uid.noteResetCameraLocked(elapsedRealtimeMs);
}
}
}
public void noteResetFlashlightLocked() {
+ noteResetFlashlightLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting > 0) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mFlashlightOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.noteResetFlashlightLocked(elapsedRealtime);
+ uid.noteResetFlashlightLocked(elapsedRealtimeMs);
}
}
}
private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
- boolean isUnoptimized) {
+ boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mBluetoothScanNesting == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
}
mBluetoothScanNesting++;
- getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
}
public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
+ noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
+ long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
- noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized);
+ noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
+ elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
- noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
+ noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
+ elapsedRealtimeMs, uptimeMs);
}
}
}
private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
- boolean isUnoptimized) {
+ boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
uid = getAttributionUid(uid, workChain);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mBluetoothScanNesting--;
if (mBluetoothScanNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
}
- getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
}
private int getAttributionUid(int uid, WorkChain workChain) {
@@ -5635,41 +5993,58 @@
}
public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
+ noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
+ long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
- noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized);
+ noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
+ elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
- noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
+ noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
+ elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteResetBluetoothScanLocked() {
+ noteResetBluetoothScanLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mBluetoothScanNesting > 0) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mBluetoothScanNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.noteResetBluetoothScanLocked(elapsedRealtime);
+ uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
}
}
}
public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
+ noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
+ long elapsedRealtimeMs, long uptimeMs) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
int uid = mapUid(ws.getUid(i));
- getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteBluetoothScanResultsLocked(numNewResults);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -5677,7 +6052,8 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain wc = workChains.get(i);
int uid = mapUid(wc.getAttributionUid());
- getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteBluetoothScanResultsLocked(numNewResults);
}
}
}
@@ -5687,55 +6063,62 @@
uid = mapUid(uid);
addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
- getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
+ getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
}
public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteWifiRadioPowerState(powerState, timestampNs, uid,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
+ long elapsedRealtimeMs, long uptimeMs) {
if (mWifiRadioPowerState != powerState) {
final boolean active =
powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
|| powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
if (active) {
if (uid > 0) {
- noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
+ noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
}
mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
- mWifiActiveTimer.startRunningLocked(elapsedRealtime);
+ mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
} else {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
- mWifiActiveTimer.stopRunningLocked(
- timestampNs / (1000 * 1000));
+ mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
}
if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiRadioPowerState = powerState;
}
}
public void noteWifiRunningLocked(WorkSource ws) {
+ noteWifiRunningLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (!mGlobalWifiRunning) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGlobalWifiRunning = true;
- mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
+ mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
int N = ws.size();
for (int i=0; i<N; i++) {
int uid = mapUid(ws.getUid(i));
- getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiRunningLocked(elapsedRealtimeMs);
}
List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
int uid = mapUid(workChains.get(i).getAttributionUid());
- getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiRunningLocked(elapsedRealtimeMs);
}
}
@@ -5746,33 +6129,42 @@
}
public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
+ noteWifiRunningChangedLocked(oldWs, newWs,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
+ long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
int N = oldWs.size();
for (int i=0; i<N; i++) {
int uid = mapUid(oldWs.getUid(i));
- getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiStoppedLocked(elapsedRealtimeMs);
}
List<WorkChain> workChains = oldWs.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
int uid = mapUid(workChains.get(i).getAttributionUid());
- getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiStoppedLocked(elapsedRealtimeMs);
}
}
N = newWs.size();
for (int i=0; i<N; i++) {
int uid = mapUid(newWs.getUid(i));
- getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiRunningLocked(elapsedRealtimeMs);
}
workChains = newWs.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
int uid = mapUid(workChains.get(i).getAttributionUid());
- getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiRunningLocked(elapsedRealtimeMs);
}
}
} else {
@@ -5781,26 +6173,30 @@
}
public void noteWifiStoppedLocked(WorkSource ws) {
+ noteWifiStoppedLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mGlobalWifiRunning = false;
- mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
+ mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
int N = ws.size();
for (int i=0; i<N; i++) {
int uid = mapUid(ws.getUid(i));
- getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiStoppedLocked(elapsedRealtimeMs);
}
List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
int uid = mapUid(workChains.get(i).getAttributionUid());
- getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiStoppedLocked(elapsedRealtimeMs);
}
}
@@ -5811,71 +6207,79 @@
}
public void noteWifiStateLocked(int wifiState, String accessPoint) {
+ noteWifiStateLocked(wifiState, accessPoint, mClocks.elapsedRealtime());
+ }
+
+ public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
if (mWifiState != wifiState) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
if (mWifiState >= 0) {
- mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
+ mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
}
mWifiState = wifiState;
- mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
+ mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
}
}
public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
+ noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
+ long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
if (mWifiSupplState != supplState) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mWifiSupplState >= 0) {
- mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
+ mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
}
mWifiSupplState = supplState;
- mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
+ mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
mHistoryCur.states2 =
(mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
| (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
- void stopAllWifiSignalStrengthTimersLocked(int except) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
+ void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
if (i == except) {
continue;
}
while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
- mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
+ mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
}
}
}
public void noteWifiRssiChangedLocked(int newRssi) {
+ noteWifiRssiChangedLocked(newRssi, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
if (mWifiSignalStrengthBin != strengthBin) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mWifiSignalStrengthBin >= 0) {
mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
- elapsedRealtime);
+ elapsedRealtimeMs);
}
if (strengthBin >= 0) {
if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
- mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
+ mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
mHistoryCur.states2 =
(mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
| (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
+ Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
} else {
- stopAllWifiSignalStrengthTimersLocked(-1);
+ stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
}
mWifiSignalStrengthBin = strengthBin;
}
@@ -5885,121 +6289,155 @@
@UnsupportedAppUsage
public void noteFullWifiLockAcquiredLocked(int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteFullWifiLockAcquiredLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiFullLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mWifiFullLockNesting++;
- getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
}
@UnsupportedAppUsage
public void noteFullWifiLockReleasedLocked(int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteFullWifiLockReleasedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
- getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
}
int mWifiScanNesting = 0;
public void noteWifiScanStartedLocked(int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteWifiScanStartedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiScanNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
mWifiScanNesting++;
- getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiScanStartedLocked(elapsedRealtimeMs);
}
public void noteWifiScanStoppedLocked(int uid) {
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ noteWifiScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
- getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiScanStoppedLocked(elapsedRealtimeMs);
}
public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
+ noteWifiBatchedScanStartedLocked(uid, csph,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiBatchedScanStartedLocked(int uid, int csph,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
}
public void noteWifiBatchedScanStoppedLocked(int uid) {
+ noteWifiBatchedScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
}
int mWifiMulticastNesting = 0;
@UnsupportedAppUsage
public void noteWifiMulticastEnabledLocked(int uid) {
+ noteWifiMulticastEnabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
if (mWifiMulticastNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
// Start Wifi Multicast overall timer
if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
- mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
+ mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
}
}
mWifiMulticastNesting++;
- getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
}
@UnsupportedAppUsage
public void noteWifiMulticastDisabledLocked(int uid) {
+ noteWifiMulticastDisabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
mWifiMulticastNesting--;
if (mWifiMulticastNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
+ Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
// Stop Wifi Multicast overall timer
if (mWifiMulticastWakelockTimer.isRunningLocked()) {
if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
- mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
+ mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
- getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
+ getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+ .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
}
public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+ noteFullWifiLockAcquiredFromSourceLocked(ws,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.getUid(i));
- noteFullWifiLockAcquiredLocked(uid);
+ noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6007,16 +6445,22 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
- noteFullWifiLockAcquiredLocked(uid);
+ noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
+ noteFullWifiLockReleasedFromSourceLocked(ws,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.getUid(i));
- noteFullWifiLockReleasedLocked(uid);
+ noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6024,16 +6468,21 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
- noteFullWifiLockReleasedLocked(uid);
+ noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
+ noteWifiScanStartedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.getUid(i));
- noteWifiScanStartedLocked(uid);
+ noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6041,16 +6490,21 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
- noteWifiScanStartedLocked(uid);
+ noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
+ noteWifiScanStoppedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.getUid(i));
- noteWifiScanStoppedLocked(uid);
+ noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6058,35 +6512,48 @@
for (int i = 0; i < workChains.size(); ++i) {
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
- noteWifiScanStoppedLocked(uid);
+ noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
+ noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteWifiBatchedScanStartedLocked(ws.getUid(i), csph);
+ noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
- noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
+ noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
+ elapsedRealtimeMs, uptimeMs);
}
}
}
public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
+ noteWifiBatchedScanStoppedFromSourceLocked(ws,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+ public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
+ long elapsedRealtimeMs, long uptimeMs) {
int N = ws.size();
for (int i=0; i<N; i++) {
- noteWifiBatchedScanStoppedLocked(ws.getUid(i));
+ noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
}
final List<WorkChain> workChains = ws.getWorkChains();
if (workChains != null) {
for (int i = 0; i < workChains.size(); ++i) {
- noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
+ noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
+ elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -6147,9 +6614,16 @@
*/
public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) {
+ noteBinderCallStats(workSourceUid, incrementalCallCount, callStats, binderThreadNativeTids,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
+ Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids,
+ long elapsedRealtimeMs, long uptimeMs) {
synchronized (this) {
- getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(incrementalCallCount,
- callStats);
+ getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
+ .noteBinderCallStatsLocked(incrementalCallCount, callStats);
mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
}
}
@@ -6182,17 +6656,17 @@
for (int i = 0; i < mUidStats.size(); i++) {
Uid uid = mUidStats.valueAt(i);
- long totalTimeForUid = 0;
+ long totalTimeForUidUs = 0;
int totalCallCountForUid = 0;
ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
for (int j = binderCallStats.size() - 1; j >= 0; j--) {
BinderCallStats stats = binderCallStats.valueAt(j);
totalCallCountForUid += stats.callCount;
if (stats.recordedCallCount > 0) {
- totalTimeForUid +=
+ totalTimeForUidUs +=
stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
} else if (totalRecordedCallCount > 0) {
- totalTimeForUid +=
+ totalTimeForUidUs +=
stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
}
}
@@ -6200,13 +6674,13 @@
if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
// Estimate remaining calls, which were not tracked because of binder call
// stats sampling
- totalTimeForUid +=
+ totalTimeForUidUs +=
(uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
/ totalRecordedCallCount;
}
- uid.mSystemServiceTimeUs = totalTimeForUid;
- totalSystemServiceTimeMicros += totalTimeForUid;
+ uid.mSystemServiceTimeUs = totalTimeForUidUs;
+ totalSystemServiceTimeMicros += totalTimeForUidUs;
}
for (int i = 0; i < mUidStats.size(); i++) {
@@ -6296,9 +6770,9 @@
@Override public long getLongestDeviceIdleModeTime(int mode) {
switch (mode) {
case DEVICE_IDLE_MODE_LIGHT:
- return mLongestLightIdleTime;
+ return mLongestLightIdleTimeMs;
case DEVICE_IDLE_MODE_DEEP:
- return mLongestFullIdleTime;
+ return mLongestFullIdleTimeMs;
}
return 0;
}
@@ -6328,12 +6802,12 @@
}
@Override public long getGpsSignalQualityTime(int strengthBin,
- long elapsedRealtimeUs, int which) {
+ long elapsedRealtimeUs, int which) {
if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
return 0;
}
return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
- elapsedRealtimeUs, which);
+ elapsedRealtimeUs, which);
}
@Override public long getGpsBatteryDrainMaMs() {
@@ -6344,11 +6818,11 @@
}
double energyUsedMaMs = 0.0;
final int which = STATS_SINCE_CHARGED;
- final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
energyUsedMaMs
- += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
- * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
+ += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
+ * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
}
return (long) energyUsedMaMs;
}
@@ -6562,18 +7036,18 @@
}
@Override public long getStartClockTime() {
- final long currentTime = System.currentTimeMillis();
- if ((currentTime > MILLISECONDS_IN_YEAR
- && mStartClockTime < (currentTime - MILLISECONDS_IN_YEAR))
- || (mStartClockTime > currentTime)) {
+ final long currentTimeMs = System.currentTimeMillis();
+ if ((currentTimeMs > MILLISECONDS_IN_YEAR
+ && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
+ || (mStartClockTimeMs > currentTimeMs)) {
// If the start clock time has changed by more than a year, then presumably
// the previous time was completely bogus. So we are going to figure out a
// new time based on how much time has elapsed since we started counting.
- recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
+ recordCurrentTimeChangeLocked(currentTimeMs, mClocks.elapsedRealtime(),
mClocks.uptimeMillis());
- return currentTime - (mClocks.elapsedRealtime() - (mRealtimeStart / 1000));
+ return currentTimeMs - (mClocks.elapsedRealtime() - (mRealtimeStartUs / 1000));
}
- return mStartClockTime;
+ return mStartClockTimeMs;
}
@Override public String getStartPlatformVersion() {
@@ -6597,29 +7071,32 @@
return mUidStats;
}
- private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) {
+ private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
+ long elapsedRealtimeUs) {
if (t != null) {
- return t.reset(detachIfReset);
+ return t.reset(detachIfReset, elapsedRealtimeUs);
}
return true;
}
- private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) {
+ private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
+ long elapsedRealtimeUs) {
if (t != null) {
boolean ret = true;
for (int i = 0; i < t.length; i++) {
- ret &= resetIfNotNull(t[i], detachIfReset);
+ ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
}
return ret;
}
return true;
}
- private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) {
+ private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
+ long elapsedRealtimeUs) {
if (t != null) {
boolean ret = true;
for (int i = 0; i < t.length; i++) {
- ret &= resetIfNotNull(t[i], detachIfReset);
+ ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
}
return ret;
}
@@ -6627,9 +7104,9 @@
}
private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
- boolean detachIfReset) {
+ boolean detachIfReset, long elapsedRealtimeUs) {
if (counter != null) {
- counter.reset(detachIfReset);
+ counter.reset(detachIfReset, elapsedRealtimeUs);
}
return true;
}
@@ -6812,10 +7289,10 @@
/**
* The CPU times we had at the last history details update.
*/
- long mLastStepUserTime;
- long mLastStepSystemTime;
- long mCurStepUserTime;
- long mCurStepSystemTime;
+ long mLastStepUserTimeMs;
+ long mLastStepSystemTimeMs;
+ long mCurStepUserTimeMs;
+ long mCurStepSystemTimeMs;
LongSamplingCounter mUserCpuTime;
LongSamplingCounter mSystemCpuTime;
@@ -6915,17 +7392,19 @@
private double mProportionalSystemServiceUsage;
public Uid(BatteryStatsImpl bsi, int uid) {
+ this(bsi, uid, bsi.mClocks.elapsedRealtime(), bsi.mClocks.uptimeMillis());
+ }
+
+ public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
mBsi = bsi;
mUid = uid;
/* Observer list of TimeBase object in Uid is short */
mOnBatteryBackgroundTimeBase = new TimeBase(false);
- mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
- mBsi.mClocks.elapsedRealtime() * 1000);
+ mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
/* Observer list of TimeBase object in Uid is short */
mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
- mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
- mBsi.mClocks.elapsedRealtime() * 1000);
+ mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
@@ -7520,13 +7999,13 @@
return mVibratorOnTimer;
}
- public void noteVibratorOnLocked(long durationMillis) {
- createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
+ public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
+ createVibratorOnTimerLocked().addDuration(mBsi, durationMillis, elapsedRealtimeMs);
}
- public void noteVibratorOffLocked() {
+ public void noteVibratorOffLocked(long elapsedRealtimeMs) {
if (mVibratorOnTimer != null) {
- mVibratorOnTimer.abortLastDuration(mBsi);
+ mVibratorOnTimer.abortLastDuration(mBsi, elapsedRealtimeMs);
}
}
@@ -7962,58 +8441,58 @@
* inactive so can be dropped.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean reset(long uptime, long realtime) {
+ public boolean reset(long uptimeUs, long realtimeUs) {
boolean active = false;
- mOnBatteryBackgroundTimeBase.init(uptime, realtime);
- mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
+ mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
+ mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
if (mWifiRunningTimer != null) {
- active |= !mWifiRunningTimer.reset(false);
+ active |= !mWifiRunningTimer.reset(false, realtimeUs);
active |= mWifiRunning;
}
if (mFullWifiLockTimer != null) {
- active |= !mFullWifiLockTimer.reset(false);
+ active |= !mFullWifiLockTimer.reset(false, realtimeUs);
active |= mFullWifiLockOut;
}
if (mWifiScanTimer != null) {
- active |= !mWifiScanTimer.reset(false);
+ active |= !mWifiScanTimer.reset(false, realtimeUs);
active |= mWifiScanStarted;
}
if (mWifiBatchedScanTimer != null) {
for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
if (mWifiBatchedScanTimer[i] != null) {
- active |= !mWifiBatchedScanTimer[i].reset(false);
+ active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
}
}
active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
}
if (mWifiMulticastTimer != null) {
- active |= !mWifiMulticastTimer.reset(false);
+ active |= !mWifiMulticastTimer.reset(false, realtimeUs);
active |= (mWifiMulticastWakelockCount > 0);
}
- active |= !resetIfNotNull(mAudioTurnedOnTimer, false);
- active |= !resetIfNotNull(mVideoTurnedOnTimer, false);
- active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false);
- active |= !resetIfNotNull(mCameraTurnedOnTimer, false);
- active |= !resetIfNotNull(mForegroundActivityTimer, false);
- active |= !resetIfNotNull(mForegroundServiceTimer, false);
- active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false);
- active |= !resetIfNotNull(mBluetoothScanTimer, false);
- active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false);
+ active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
+ active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
- resetIfNotNull(mBluetoothScanResultCounter, false);
- resetIfNotNull(mBluetoothScanResultBgCounter, false);
+ resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
+ resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
if (mProcessStateTimer != null) {
for (int i = 0; i < NUM_PROCESS_STATE; i++) {
- active |= !resetIfNotNull(mProcessStateTimer[i], false);
+ active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
}
active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
}
if (mVibratorOnTimer != null) {
- if (mVibratorOnTimer.reset(false)) {
+ if (mVibratorOnTimer.reset(false, realtimeUs)) {
mVibratorOnTimer.detach();
mVibratorOnTimer = null;
} else {
@@ -8021,80 +8500,81 @@
}
}
- resetIfNotNull(mUserActivityCounters, false);
+ resetIfNotNull(mUserActivityCounters, false, realtimeUs);
- resetIfNotNull(mNetworkByteActivityCounters, false);
- resetIfNotNull(mNetworkPacketActivityCounters, false);
- resetIfNotNull(mMobileRadioActiveTime, false);
- resetIfNotNull(mMobileRadioActiveCount, false);
+ resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
+ resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
+ resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
+ resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
- resetIfNotNull(mWifiControllerActivity, false);
- resetIfNotNull(mBluetoothControllerActivity, false);
- resetIfNotNull(mModemControllerActivity, false);
+ resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
+ resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
+ resetIfNotNull(mModemControllerActivity, false, realtimeUs);
- resetIfNotNull(mUserCpuTime, false);
- resetIfNotNull(mSystemCpuTime, false);
+ resetIfNotNull(mUserCpuTime, false, realtimeUs);
+ resetIfNotNull(mSystemCpuTime, false, realtimeUs);
- resetIfNotNull(mCpuClusterSpeedTimesUs, false);
+ resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
- resetIfNotNull(mCpuFreqTimeMs, false);
- resetIfNotNull(mScreenOffCpuFreqTimeMs, false);
+ resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
+ resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
- resetIfNotNull(mCpuActiveTimeMs, false);
- resetIfNotNull(mCpuClusterTimesMs, false);
+ resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
+ resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
- resetIfNotNull(mProcStateTimeMs, false);
+ resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
- resetIfNotNull(mProcStateScreenOffTimeMs, false);
+ resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
- resetIfNotNull(mMobileRadioApWakeupCount, false);
+ resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
- resetIfNotNull(mWifiRadioApWakeupCount, false);
+ resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
for (int iw=wakeStats.size()-1; iw>=0; iw--) {
Wakelock wl = wakeStats.valueAt(iw);
- if (wl.reset()) {
+ if (wl.reset(realtimeUs)) {
wakeStats.removeAt(iw);
} else {
active = true;
}
}
- mWakelockStats.cleanup();
+ final long realtimeMs = realtimeUs / 1000;
+ mWakelockStats.cleanup(realtimeMs);
final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
for (int is=syncStats.size()-1; is>=0; is--) {
DualTimer timer = syncStats.valueAt(is);
- if (timer.reset(false)) {
+ if (timer.reset(false, realtimeUs)) {
syncStats.removeAt(is);
timer.detach();
} else {
active = true;
}
}
- mSyncStats.cleanup();
+ mSyncStats.cleanup(realtimeMs);
final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
for (int ij=jobStats.size()-1; ij>=0; ij--) {
DualTimer timer = jobStats.valueAt(ij);
- if (timer.reset(false)) {
+ if (timer.reset(false, realtimeUs)) {
jobStats.removeAt(ij);
timer.detach();
} else {
active = true;
}
}
- mJobStats.cleanup();
+ mJobStats.cleanup(realtimeMs);
mJobCompletions.clear();
- resetIfNotNull(mJobsDeferredEventCount, false);
- resetIfNotNull(mJobsDeferredCount, false);
- resetIfNotNull(mJobsFreshnessTimeMs, false);
- resetIfNotNull(mJobsFreshnessBuckets, false);
+ resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
+ resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
+ resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
+ resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
Sensor s = mSensorStats.valueAt(ise);
- if (s.reset()) {
+ if (s.reset(realtimeUs)) {
mSensorStats.removeAt(ise);
} else {
active = true;
@@ -8128,8 +8608,8 @@
mProportionalSystemServiceUsage = 0;
- mLastStepUserTime = mLastStepSystemTime = 0;
- mCurStepUserTime = mCurStepSystemTime = 0;
+ mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
+ mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
return !active;
@@ -8943,13 +9423,13 @@
return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
}
- boolean reset() {
+ boolean reset(long elapsedRealtimeUs) {
boolean wlactive = false;
- wlactive |= !resetIfNotNull(mTimerFull,false);
- wlactive |= !resetIfNotNull(mTimerPartial,false);
- wlactive |= !resetIfNotNull(mTimerWindow,false);
- wlactive |= !resetIfNotNull(mTimerDraw,false);
+ wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
+ wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
+ wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
+ wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
if (!wlactive) {
detachIfNotNull(mTimerFull);
@@ -9040,8 +9520,8 @@
return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
}
- boolean reset() {
- if (mTimer.reset(true)) {
+ boolean reset(long elapsedRealtimeUs) {
+ if (mTimer.reset(true, elapsedRealtimeUs)) {
mTimer = null;
return true;
}
@@ -9103,17 +9583,17 @@
/**
* Total time (in ms) spent executing in user code.
*/
- long mUserTime;
+ long mUserTimeMs;
/**
* Total time (in ms) spent executing in kernel code.
*/
- long mSystemTime;
+ long mSystemTimeMs;
/**
* Amount of time (in ms) the process was running in the foreground.
*/
- long mForegroundTime;
+ long mForegroundTimeMs;
/**
* Number of times the process has been started.
@@ -9138,14 +9618,16 @@
mBsi.mOnBatteryTimeBase.add(this);
}
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
if (detachIfReset) {
this.detach();
}
@@ -9169,14 +9651,14 @@
return null;
}
- public void addExcessiveCpu(long overTime, long usedTime) {
+ public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
if (mExcessivePower == null) {
mExcessivePower = new ArrayList<ExcessivePower>();
}
ExcessivePower ew = new ExcessivePower();
ew.type = ExcessivePower.TYPE_CPU;
- ew.overTime = overTime;
- ew.usedTime = usedTime;
+ ew.overTime = overTimeMs;
+ ew.usedTime = usedTimeMs;
mExcessivePower.add(ew);
}
@@ -9219,9 +9701,9 @@
}
void writeToParcelLocked(Parcel out) {
- out.writeLong(mUserTime);
- out.writeLong(mSystemTime);
- out.writeLong(mForegroundTime);
+ out.writeLong(mUserTimeMs);
+ out.writeLong(mSystemTimeMs);
+ out.writeLong(mForegroundTimeMs);
out.writeInt(mStarts);
out.writeInt(mNumCrashes);
out.writeInt(mNumAnrs);
@@ -9229,9 +9711,9 @@
}
void readFromParcelLocked(Parcel in) {
- mUserTime = in.readLong();
- mSystemTime = in.readLong();
- mForegroundTime = in.readLong();
+ mUserTimeMs = in.readLong();
+ mSystemTimeMs = in.readLong();
+ mForegroundTimeMs = in.readLong();
mStarts = in.readInt();
mNumCrashes = in.readInt();
mNumAnrs = in.readInt();
@@ -9239,20 +9721,20 @@
}
@UnsupportedAppUsage
- public void addCpuTimeLocked(int utime, int stime) {
- addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
+ public void addCpuTimeLocked(int utimeMs, int stimeMs) {
+ addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
}
- public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
+ public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
if (isRunning) {
- mUserTime += utime;
- mSystemTime += stime;
+ mUserTimeMs += utimeMs;
+ mSystemTimeMs += stimeMs;
}
}
@UnsupportedAppUsage
- public void addForegroundTimeLocked(long ttime) {
- mForegroundTime += ttime;
+ public void addForegroundTimeLocked(long ttimeMs) {
+ mForegroundTimeMs += ttimeMs;
}
@UnsupportedAppUsage
@@ -9276,19 +9758,19 @@
@Override
@UnsupportedAppUsage
public long getUserTime(int which) {
- return mUserTime;
+ return mUserTimeMs;
}
@Override
@UnsupportedAppUsage
public long getSystemTime(int which) {
- return mSystemTime;
+ return mSystemTimeMs;
}
@Override
@UnsupportedAppUsage
public long getForegroundTime(int which) {
- return mForegroundTime;
+ return mForegroundTimeMs;
}
@Override
@@ -9333,14 +9815,16 @@
mBsi.mOnBatteryScreenOffTimeBase.add(this);
}
- public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
- public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
if (detachIfReset) {
this.detach();
}
@@ -9430,13 +9914,13 @@
/**
* Total time (ms in battery uptime) the service has been left started.
*/
- protected long mStartTime;
+ protected long mStartTimeMs;
/**
* If service has been started and not yet stopped, this is
* when it was started.
*/
- protected long mRunningSince;
+ protected long mRunningSinceMs;
/**
* True if we are currently running.
@@ -9451,13 +9935,13 @@
/**
* Total time (ms in battery uptime) the service has been left launched.
*/
- protected long mLaunchedTime;
+ protected long mLaunchedTimeMs;
/**
* If service has been launched and not yet exited, this is
* when it was launched (ms in battery uptime).
*/
- protected long mLaunchedSince;
+ protected long mLaunchedSinceMs;
/**
* True if we are currently launched.
@@ -9477,16 +9961,16 @@
mBsi.mOnBatteryTimeBase.add(this);
}
- public void onTimeStarted(long elapsedRealtime, long baseUptime,
- long baseRealtime) {
+ public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
- public void onTimeStopped(long elapsedRealtime, long baseUptime,
- long baseRealtime) {
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
+ long baseRealtimeUs) {
}
@Override
- public boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
if (detachIfReset) {
this.detach();
}
@@ -9495,59 +9979,68 @@
/**
* Remove this Serv as a listener from the time base.
- */
+ Ms*/
@Override
public void detach() {
mBsi.mOnBatteryTimeBase.remove(this);
}
public void readFromParcelLocked(Parcel in) {
- mStartTime = in.readLong();
- mRunningSince = in.readLong();
+ mStartTimeMs = in.readLong();
+ mRunningSinceMs = in.readLong();
mRunning = in.readInt() != 0;
mStarts = in.readInt();
- mLaunchedTime = in.readLong();
- mLaunchedSince = in.readLong();
+ mLaunchedTimeMs = in.readLong();
+ mLaunchedSinceMs = in.readLong();
mLaunched = in.readInt() != 0;
mLaunches = in.readInt();
}
public void writeToParcelLocked(Parcel out) {
- out.writeLong(mStartTime);
- out.writeLong(mRunningSince);
+ out.writeLong(mStartTimeMs);
+ out.writeLong(mRunningSinceMs);
out.writeInt(mRunning ? 1 : 0);
out.writeInt(mStarts);
- out.writeLong(mLaunchedTime);
- out.writeLong(mLaunchedSince);
+ out.writeLong(mLaunchedTimeMs);
+ out.writeLong(mLaunchedSinceMs);
out.writeInt(mLaunched ? 1 : 0);
out.writeInt(mLaunches);
}
- public long getLaunchTimeToNowLocked(long batteryUptime) {
- if (!mLaunched) return mLaunchedTime;
- return mLaunchedTime + batteryUptime - mLaunchedSince;
+ public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
+ if (!mLaunched) return mLaunchedTimeMs;
+ return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
}
- public long getStartTimeToNowLocked(long batteryUptime) {
- if (!mRunning) return mStartTime;
- return mStartTime + batteryUptime - mRunningSince;
+ public long getStartTimeToNowLocked(long batteryUptimeMs) {
+ if (!mRunning) return mStartTimeMs;
+ return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
}
@UnsupportedAppUsage
public void startLaunchedLocked() {
+ startLaunchedLocked(mBsi.mClocks.uptimeMillis());
+ }
+
+ public void startLaunchedLocked(long uptimeMs) {
if (!mLaunched) {
mLaunches++;
- mLaunchedSince = mBsi.getBatteryUptimeLocked();
+ mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
mLaunched = true;
}
}
@UnsupportedAppUsage
public void stopLaunchedLocked() {
+ stopLaunchedLocked(mBsi.mClocks.uptimeMillis());
+ }
+
+ public void stopLaunchedLocked(long uptimeMs) {
if (mLaunched) {
- long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
- if (time > 0) {
- mLaunchedTime += time;
+ long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
+ - mLaunchedSinceMs;
+ if (timeMs > 0) {
+ mLaunchedTimeMs += timeMs;
} else {
mLaunches--;
}
@@ -9557,19 +10050,28 @@
@UnsupportedAppUsage
public void startRunningLocked() {
+ startRunningLocked(mBsi.mClocks.uptimeMillis());
+ }
+
+ public void startRunningLocked(long uptimeMs) {
if (!mRunning) {
mStarts++;
- mRunningSince = mBsi.getBatteryUptimeLocked();
+ mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
mRunning = true;
}
}
@UnsupportedAppUsage
public void stopRunningLocked() {
+ stopRunningLocked(mBsi.mClocks.uptimeMillis());
+ }
+
+ public void stopRunningLocked(long uptimeMs) {
if (mRunning) {
- long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
- if (time > 0) {
- mStartTime += time;
+ long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
+ - mRunningSinceMs;
+ if (timeMs > 0) {
+ mStartTimeMs += timeMs;
} else {
mStarts--;
}
@@ -9619,6 +10121,12 @@
@GuardedBy("mBsi")
public void updateUidProcessStateLocked(int procState) {
+ updateUidProcessStateLocked(procState,
+ mBsi.mClocks.elapsedRealtime(), mBsi.mClocks.uptimeMillis());
+ }
+
+ public void updateUidProcessStateLocked(int procState,
+ long elapsedRealtimeMs, long uptimeMs) {
int uidRunningState;
// Make special note of Foreground Services
final boolean userAwareService =
@@ -9629,10 +10137,7 @@
return;
}
- final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
if (mProcessState != uidRunningState) {
- final long uptimeMs = mBsi.mClocks.uptimeMillis();
-
if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
@@ -9789,28 +10294,28 @@
}
public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
- DualTimer t = mSyncStats.startObject(name);
+ DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
}
public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
- DualTimer t = mSyncStats.stopObject(name);
+ DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
}
}
public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
- DualTimer t = mJobStats.startObject(name);
+ DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
}
public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
- DualTimer t = mJobStats.stopObject(name);
+ DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
}
@@ -9873,7 +10378,7 @@
}
public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
- Wakelock wl = mWakelockStats.startObject(name);
+ Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
if (wl != null) {
getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
}
@@ -9889,7 +10394,7 @@
}
public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
- Wakelock wl = mWakelockStats.stopObject(name);
+ Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
if (wl != null) {
StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
wlt.stopRunningLocked(elapsedRealtimeMs);
@@ -9910,10 +10415,10 @@
}
}
- public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
+ public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
Proc p = getProcessStatsLocked(proc);
if (p != null) {
- p.addExcessiveCpu(overTime, usedTime);
+ p.addExcessiveCpu(overTimeMs, usedTimeMs);
}
}
@@ -10041,16 +10546,16 @@
mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
mOnBattery = mOnBatteryInternal = false;
- long uptime = mClocks.uptimeMillis() * 1000;
- long realtime = mClocks.elapsedRealtime() * 1000;
- initTimes(uptime, realtime);
+ long uptimeUs = mClocks.uptimeMillis() * 1000;
+ long realtimeUs = mClocks.elapsedRealtime() * 1000;
+ initTimes(uptimeUs, realtimeUs);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
mDischargeStartLevel = 0;
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
mCurrentBatteryLevel = 0;
- initDischarge();
+ initDischarge(realtimeUs);
clearHistoryLocked();
updateDailyDeadlineLocked();
mPlatformIdleStateCallback = cb;
@@ -10110,9 +10615,9 @@
mCallback = cb;
}
- public void setRadioScanningTimeoutLocked(long timeout) {
+ public void setRadioScanningTimeoutLocked(long timeoutUs) {
if (mPhoneSignalScanningTimer != null) {
- mPhoneSignalScanningTimer.setTimeout(timeout);
+ mPhoneSignalScanningTimer.setTimeout(timeoutUs);
}
}
@@ -10122,9 +10627,9 @@
public void updateDailyDeadlineLocked() {
// Get the current time.
- long currentTime = mDailyStartTime = System.currentTimeMillis();
+ long currentTimeMs = mDailyStartTimeMs = System.currentTimeMillis();
Calendar calDeadline = Calendar.getInstance();
- calDeadline.setTimeInMillis(currentTime);
+ calDeadline.setTimeInMillis(currentTimeMs);
// Move time up to the next day, ranging from 1am to 3pm.
calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
@@ -10132,25 +10637,24 @@
calDeadline.set(Calendar.SECOND, 0);
calDeadline.set(Calendar.MINUTE, 0);
calDeadline.set(Calendar.HOUR_OF_DAY, 1);
- mNextMinDailyDeadline = calDeadline.getTimeInMillis();
+ mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
calDeadline.set(Calendar.HOUR_OF_DAY, 3);
- mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
+ mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
}
- public void recordDailyStatsIfNeededLocked(boolean settled) {
- long currentTime = System.currentTimeMillis();
- if (currentTime >= mNextMaxDailyDeadline) {
+ public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
+ if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
recordDailyStatsLocked();
- } else if (settled && currentTime >= mNextMinDailyDeadline) {
+ } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
recordDailyStatsLocked();
- } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
+ } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
recordDailyStatsLocked();
}
}
public void recordDailyStatsLocked() {
DailyItem item = new DailyItem();
- item.mStartTime = mDailyStartTime;
+ item.mStartTime = mDailyStartTimeMs;
item.mEndTime = System.currentTimeMillis();
boolean hasData = false;
if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
@@ -10175,7 +10679,7 @@
updateDailyDeadlineLocked();
if (hasData) {
- final long startTime = SystemClock.uptimeMillis();
+ final long startTimeMs = SystemClock.uptimeMillis();
mDailyItems.add(item);
while (mDailyItems.size() > MAX_DAILY_ITEMS) {
mDailyItems.remove(0);
@@ -10185,12 +10689,12 @@
XmlSerializer out = new FastXmlSerializer();
out.setOutput(memStream, StandardCharsets.UTF_8.name());
writeDailyItemsLocked(out);
- final long initialTime = SystemClock.uptimeMillis() - startTime;
+ final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
synchronized (mCheckinFile) {
- final long startTime2 = SystemClock.uptimeMillis();
+ final long startTimeMs2 = SystemClock.uptimeMillis();
FileOutputStream stream = null;
try {
stream = mDailyFile.startWrite();
@@ -10199,7 +10703,7 @@
mDailyFile.finishWrite(stream);
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
"batterystats-daily",
- initialTime + SystemClock.uptimeMillis() - startTime2);
+ initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
} catch (IOException e) {
Slog.w("BatteryStats",
"Error writing battery daily items", e);
@@ -10431,17 +10935,17 @@
@Override
public long getCurrentDailyStartTime() {
- return mDailyStartTime;
+ return mDailyStartTimeMs;
}
@Override
public long getNextMinDailyDeadline() {
- return mNextMinDailyDeadline;
+ return mNextMinDailyDeadlineMs;
}
@Override
public long getNextMaxDailyDeadline() {
- return mNextMaxDailyDeadline;
+ return mNextMaxDailyDeadlineMs;
}
@Override
@@ -10554,12 +11058,12 @@
if (p == null) {
return false;
}
- final long lastRealtime = out.time;
- final long lastWalltime = out.currentTime;
+ final long lastRealtimeMs = out.time;
+ final long lastWalltimeMs = out.currentTime;
readHistoryDelta(p, out);
if (out.cmd != HistoryItem.CMD_CURRENT_TIME
- && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
- out.currentTime = lastWalltime + (out.time - lastRealtime);
+ && out.cmd != HistoryItem.CMD_RESET && lastWalltimeMs != 0) {
+ out.currentTime = lastWalltimeMs + (out.time - lastRealtimeMs);
}
return true;
}
@@ -10574,7 +11078,7 @@
@Override
public long getHistoryBaseTime() {
- return mHistoryBaseTime;
+ return mHistoryBaseTimeMs;
}
@Override
@@ -10604,17 +11108,17 @@
return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
}
- void initTimes(long uptime, long realtime) {
- mStartClockTime = System.currentTimeMillis();
- mOnBatteryTimeBase.init(uptime, realtime);
- mOnBatteryScreenOffTimeBase.init(uptime, realtime);
- mRealtime = 0;
- mUptime = 0;
- mRealtimeStart = realtime;
- mUptimeStart = uptime;
+ void initTimes(long uptimeUs, long realtimeUs) {
+ mStartClockTimeMs = System.currentTimeMillis();
+ mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
+ mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
+ mRealtimeUs = 0;
+ mUptimeUs = 0;
+ mRealtimeStartUs = realtimeUs;
+ mUptimeStartUs = uptimeUs;
}
- void initDischarge() {
+ void initDischarge(long elapsedRealtimeUs) {
mLowDischargeAmountSinceCharge = 0;
mHighDischargeAmountSinceCharge = 0;
mDischargeAmountScreenOn = 0;
@@ -10625,26 +11129,26 @@
mDischargeAmountScreenDozeSinceCharge = 0;
mDischargeStepTracker.init();
mChargeStepTracker.init();
- mDischargeScreenOffCounter.reset(false);
- mDischargeScreenDozeCounter.reset(false);
- mDischargeLightDozeCounter.reset(false);
- mDischargeDeepDozeCounter.reset(false);
- mDischargeCounter.reset(false);
+ mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
+ mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
+ mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
+ mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
+ mDischargeCounter.reset(false, elapsedRealtimeUs);
}
public void resetAllStatsCmdLocked() {
- resetAllStatsLocked();
final long mSecUptime = mClocks.uptimeMillis();
- long uptime = mSecUptime * 1000;
+ long uptimeUs = mSecUptime * 1000;
long mSecRealtime = mClocks.elapsedRealtime();
- long realtime = mSecRealtime * 1000;
+ long realtimeUs = mSecRealtime * 1000;
+ resetAllStatsLocked(mSecUptime, mSecRealtime);
mDischargeStartLevel = mHistoryCur.batteryLevel;
pullPendingStateUpdatesLocked();
addHistoryRecordLocked(mSecRealtime, mSecUptime);
mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
= mCurrentBatteryLevel = mHistoryCur.batteryLevel;
- mOnBatteryTimeBase.reset(uptime, realtime);
- mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
+ mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
+ mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
if (isScreenOn(mScreenState)) {
mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
@@ -10666,15 +11170,15 @@
initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
}
- private void resetAllStatsLocked() {
- final long uptimeMillis = mClocks.uptimeMillis();
- final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
+ private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis) {
+ final long uptimeUs = uptimeMillis * 1000;
+ final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
mStartCount = 0;
- initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
- mScreenOnTimer.reset(false);
- mScreenDozeTimer.reset(false);
+ initTimes(uptimeUs, elapsedRealtimeUs);
+ mScreenOnTimer.reset(false, uptimeUs);
+ mScreenDozeTimer.reset(false, elapsedRealtimeUs);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i].reset(false);
+ mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
}
if (mPowerProfile != null) {
@@ -10684,60 +11188,60 @@
}
mMinLearnedBatteryCapacity = -1;
mMaxLearnedBatteryCapacity = -1;
- mInteractiveTimer.reset(false);
- mPowerSaveModeEnabledTimer.reset(false);
- mLastIdleTimeStart = elapsedRealtimeMillis;
- mLongestLightIdleTime = 0;
- mLongestFullIdleTime = 0;
- mDeviceIdleModeLightTimer.reset(false);
- mDeviceIdleModeFullTimer.reset(false);
- mDeviceLightIdlingTimer.reset(false);
- mDeviceIdlingTimer.reset(false);
- mPhoneOnTimer.reset(false);
- mAudioOnTimer.reset(false);
- mVideoOnTimer.reset(false);
- mFlashlightOnTimer.reset(false);
- mCameraOnTimer.reset(false);
- mBluetoothScanTimer.reset(false);
+ mInteractiveTimer.reset(false, elapsedRealtimeUs);
+ mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
+ mLastIdleTimeStartMs = elapsedRealtimeMillis;
+ mLongestLightIdleTimeMs = 0;
+ mLongestFullIdleTimeMs = 0;
+ mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
+ mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
+ mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
+ mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
+ mPhoneOnTimer.reset(false, elapsedRealtimeUs);
+ mAudioOnTimer.reset(false, elapsedRealtimeUs);
+ mVideoOnTimer.reset(false, elapsedRealtimeUs);
+ mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
+ mCameraOnTimer.reset(false, elapsedRealtimeUs);
+ mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
- mPhoneSignalStrengthsTimer[i].reset(false);
+ mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
}
- mPhoneSignalScanningTimer.reset(false);
+ mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i].reset(false);
+ mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
}
for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
- mNetworkByteActivityCounters[i].reset(false);
- mNetworkPacketActivityCounters[i].reset(false);
+ mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
+ mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
}
- mMobileRadioActiveTimer.reset(false);
- mMobileRadioActivePerAppTimer.reset(false);
- mMobileRadioActiveAdjustedTime.reset(false);
- mMobileRadioActiveUnknownTime.reset(false);
- mMobileRadioActiveUnknownCount.reset(false);
- mWifiOnTimer.reset(false);
- mGlobalWifiRunningTimer.reset(false);
+ mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
+ mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
+ mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
+ mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
+ mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
+ mWifiOnTimer.reset(false, elapsedRealtimeUs);
+ mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
for (int i=0; i<NUM_WIFI_STATES; i++) {
- mWifiStateTimer[i].reset(false);
+ mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
}
for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
- mWifiSupplStateTimer[i].reset(false);
+ mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
}
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
- mWifiSignalStrengthsTimer[i].reset(false);
+ mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
}
- mWifiMulticastWakelockTimer.reset(false);
- mWifiActiveTimer.reset(false);
- mWifiActivity.reset(false);
+ mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
+ mWifiActiveTimer.reset(false, elapsedRealtimeUs);
+ mWifiActivity.reset(false, elapsedRealtimeUs);
for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
- mGpsSignalQualityTimer[i].reset(false);
+ mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
}
- mBluetoothActivity.reset(false);
- mModemActivity.reset(false);
+ mBluetoothActivity.reset(false, elapsedRealtimeUs);
+ mModemActivity.reset(false, elapsedRealtimeUs);
mNumConnectivityChange = 0;
for (int i=0; i<mUidStats.size(); i++) {
- if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
+ if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs)) {
mUidStats.valueAt(i).detachFromTimeBase();
mUidStats.remove(mUidStats.keyAt(i));
i--;
@@ -10780,25 +11284,25 @@
mTmpRailStats.reset();
- resetIfNotNull(mSystemServerThreadCpuTimesUs, false);
- resetIfNotNull(mBinderThreadCpuTimesUs, false);
+ resetIfNotNull(mSystemServerThreadCpuTimesUs, false, elapsedRealtimeUs);
+ resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
mLastHistoryStepDetails = null;
- mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
- mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
- mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
- mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
- mLastStepStatUserTime = mCurStepStatUserTime = 0;
- mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
- mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
- mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
- mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
- mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
+ mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
+ mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
mNumAllUidCpuTimeReads = 0;
mNumUidsRemoved = 0;
- initDischarge();
+ initDischarge(elapsedRealtimeUs);
clearHistoryLocked();
mBatteryStatsHistory.resetAllFiles();
@@ -10915,6 +11419,14 @@
* @param info The energy information from the WiFi controller.
*/
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
+ updateWifiState(info, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see #updateWifiState(WifiActivityEnergyInfo)
+ */
+ public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
+ long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
}
@@ -10939,7 +11451,6 @@
return;
}
- final long elapsedRealtimeMs = mClocks.elapsedRealtime();
SparseLongArray rxPackets = new SparseLongArray();
SparseLongArray txPackets = new SparseLongArray();
long totalTxPackets = 0;
@@ -10961,7 +11472,7 @@
continue;
}
- final Uid u = getUidStatsLocked(mapUid(entry.uid));
+ final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
if (entry.rxBytes != 0) {
u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
entry.rxPackets);
@@ -11127,7 +11638,8 @@
// Distribute the remaining Tx power appropriately between all apps that transmitted
// packets.
for (int i = 0; i < txPackets.size(); i++) {
- final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
+ final Uid uid = getUidStatsLocked(txPackets.keyAt(i),
+ elapsedRealtimeMs, uptimeMs);
final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
/ totalTxPackets;
if (DEBUG_ENERGY) {
@@ -11140,7 +11652,8 @@
// Distribute the remaining Rx power appropriately between all apps that received
// packets.
for (int i = 0; i < rxPackets.size(); i++) {
- final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
+ final Uid uid = getUidStatsLocked(rxPackets.keyAt(i),
+ elapsedRealtimeMs, uptimeMs);
final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
/ totalRxPackets;
if (DEBUG_ENERGY) {
@@ -11179,7 +11692,7 @@
monitoredRailChargeConsumedMaMs);
mHistoryCur.wifiRailChargeMah +=
(monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetWifiTotalEnergyUsed();
}
}
@@ -11210,13 +11723,21 @@
* Distribute Cell radio energy info and network traffic to apps.
*/
public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
+ updateMobileRadioState(activityInfo, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see #updateMobileRadioState(ModemActivityInfo)
+ */
+ public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo,
+ long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
}
ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
// Add modem tx power to history.
- addModemTxPowerToHistory(deltaInfo);
+ addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null;
@@ -11279,12 +11800,11 @@
monitoredRailChargeConsumedMaMs);
mHistoryCur.modemRailChargeMah +=
(monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetCellularTotalEnergyUsed();
}
}
- final long elapsedRealtimeMs = mClocks.elapsedRealtime();
- long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
+ long radioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
@@ -11308,7 +11828,7 @@
totalRxPackets += entry.rxPackets;
totalTxPackets += entry.txPackets;
- final Uid u = getUidStatsLocked(mapUid(entry.uid));
+ final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
@@ -11339,16 +11859,17 @@
continue;
}
- final Uid u = getUidStatsLocked(mapUid(entry.uid));
+ final Uid u = getUidStatsLocked(mapUid(entry.uid),
+ elapsedRealtimeMs, uptimeMs);
// Distribute total radio active time in to this app.
final long appPackets = entry.rxPackets + entry.txPackets;
- final long appRadioTime = (radioTime * appPackets) / totalPackets;
- u.noteMobileRadioActiveTimeLocked(appRadioTime);
+ final long appRadioTimeUs = (radioTimeUs * appPackets) / totalPackets;
+ u.noteMobileRadioActiveTimeLocked(appRadioTimeUs);
// Remove this app from the totals, so that we don't lose any time
// due to rounding.
- radioTime -= appRadioTime;
+ radioTimeUs -= appRadioTimeUs;
totalPackets -= appPackets;
if (deltaInfo != null) {
@@ -11373,9 +11894,9 @@
}
}
- if (radioTime > 0) {
+ if (radioTimeUs > 0) {
// Whoops, there is some radio time we can't blame on an app!
- mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+ mMobileRadioActiveUnknownTime.addCountLocked(radioTimeUs);
mMobileRadioActiveUnknownCount.addCountLocked(1);
}
@@ -11391,7 +11912,8 @@
* time at the highest power level.
* @param activityInfo
*/
- private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
+ private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
+ long elapsedRealtimeMs, long uptimeMs) {
if (activityInfo == null) {
return;
}
@@ -11399,8 +11921,6 @@
if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
return;
}
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
int levelMaxTimeSpent = 0;
for (int i = 1; i < txPowerInfo.size(); i++) {
if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
@@ -11410,7 +11930,7 @@
}
if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -11446,6 +11966,14 @@
* @param info The energy information from the bluetooth controller.
*/
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
+ updateBluetoothStateLocked(info, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see #updateBluetoothStateLocked(BluetoothActivityEnergyInfo)
+ */
+ public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
+ long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating bluetooth stats: " + info);
}
@@ -11456,7 +11984,6 @@
mHasBluetoothReporting = true;
- final long elapsedRealtimeMs = mClocks.elapsedRealtime();
final long rxTimeMs =
info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
final long txTimeMs =
@@ -11560,7 +12087,7 @@
mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
// Add to the UID counters.
- final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
+ final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
@@ -11579,7 +12106,7 @@
final long txBytes =
traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
- final Uid u = getUidStatsLocked(mapUid(uid));
+ final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
final ControllerActivityCounterImpl counter =
u.getOrCreateBluetoothControllerActivityLocked();
@@ -11623,6 +12150,13 @@
* instead of fetching it anew.
*/
public void updateRpmStatsLocked() {
+ updateRpmStatsLocked(mClocks.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #updateRpmStatsLocked()
+ */
+ public void updateRpmStatsLocked(long elapsedRealtimeUs) {
if (mPlatformIdleStateCallback == null) return;
long now = SystemClock.elapsedRealtime();
if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
@@ -11637,9 +12171,9 @@
final String pName = pstate.getKey();
final long pTimeUs = pstate.getValue().mTimeMs * 1000;
final int pCount = pstate.getValue().mCount;
- getRpmTimerLocked(pName).update(pTimeUs, pCount);
+ getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
if (SCREEN_OFF_RPM_STATS_ENABLED) {
- getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
+ getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
}
// Update values for each voter of this platform state.
@@ -11648,9 +12182,9 @@
final String vName = pName + "." + voter.getKey();
final long vTimeUs = voter.getValue().mTimeMs * 1000;
final int vCount = voter.getValue().mCount;
- getRpmTimerLocked(vName).update(vTimeUs, vCount);
+ getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
if (SCREEN_OFF_RPM_STATS_ENABLED) {
- getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
+ getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
}
}
}
@@ -11664,9 +12198,9 @@
final String name = subsysName + "." + sstate.getKey();
final long timeUs = sstate.getValue().mTimeMs * 1000;
final int count = sstate.getValue().mCount;
- getRpmTimerLocked(name).update(timeUs, count);
+ getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
if (SCREEN_OFF_RPM_STATS_ENABLED) {
- getScreenOffRpmTimerLocked(name).update(timeUs, count);
+ getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
}
}
}
@@ -11686,6 +12220,13 @@
* Read and distribute kernel wake lock use across apps.
*/
public void updateKernelWakelocksLocked() {
+ updateKernelWakelocksLocked(mClocks.elapsedRealtime() * 1000);
+ }
+
+ /**
+ * @see #updateKernelWakelocksLocked()
+ */
+ public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
mTmpWakelockStats);
if (wakelockStats == null) {
@@ -11704,7 +12245,7 @@
mKernelWakelockStats.put(name, kwlt);
}
- kwlt.update(kws.mTotalTime, kws.mCount);
+ kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
kwlt.setUpdateVersion(kws.mVersion);
}
@@ -11714,7 +12255,7 @@
for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
SamplingTimer st = ent.getValue();
if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
- st.endSample();
+ st.endSample(elapsedRealtimeUs);
numWakelocksSetStale++;
}
}
@@ -11742,6 +12283,10 @@
* Reads the newest memory stats from the kernel.
*/
public void updateKernelMemoryBandwidthLocked() {
+ updateKernelMemoryBandwidthLocked(mClocks.elapsedRealtime() * 1000);
+ }
+
+ public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
mKernelMemoryBandwidthStats.updateStats();
LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
final int bandwidthEntryCount = bandwidthEntries.size();
@@ -11754,12 +12299,12 @@
timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
}
- timer.update(bandwidthEntries.valueAt(i), 1);
+ timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
if (DEBUG_MEMORY) {
Slog.d(TAG, String.format("Added entry %d and updated timer to: "
- + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
+ + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
mKernelMemoryStats.get(
- bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
+ bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
mKernelMemoryStats.size()));
}
}
@@ -11898,8 +12443,8 @@
}
if (DEBUG_BINDER_STATS) {
Slog.d(TAG, "System server threads per CPU cluster (binder threads/total threads/%)");
- long binderThreadTime = 0;
- long totalThreadTime = 0;
+ long binderThreadTimeMs = 0;
+ long totalThreadTimeMs = 0;
int cpuIndex = 0;
for (int cluster = 0; cluster < numCpuClusters; cluster++) {
StringBuilder sb = new StringBuilder();
@@ -11909,26 +12454,27 @@
if (speed != 0) {
sb.append(", ");
}
- long totalCount = mSystemServerThreadCpuTimesUs[cluster][speed].getCountLocked(
- 0) / 1000;
- long binderCount = mBinderThreadCpuTimesUs[cluster][speed].getCountLocked(0)
+ long totalCountMs =
+ mSystemServerThreadCpuTimesUs[cluster][speed].getCountLocked(0) / 1000;
+ long binderCountMs = mBinderThreadCpuTimesUs[cluster][speed].getCountLocked(0)
/ 1000;
sb.append(String.format("%d/%d(%.1f%%)",
- binderCount,
- totalCount,
- totalCount != 0 ? (double) binderCount * 100 / totalCount : 0));
+ binderCountMs,
+ totalCountMs,
+ totalCountMs != 0 ? (double) binderCountMs * 100 / totalCountMs : 0));
- totalThreadTime += totalCount;
- binderThreadTime += binderCount;
+ totalThreadTimeMs += totalCountMs;
+ binderThreadTimeMs += binderCountMs;
index++;
}
cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
Slog.d(TAG, sb.toString());
}
- Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTime);
+ Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTimeMs);
Slog.d(TAG, String.format("Total Binder thread time (ms): %d (%.1f%%)",
- binderThreadTime,
- binderThreadTime != 0 ? (double) binderThreadTime * 100 / totalThreadTime : 0));
+ binderThreadTimeMs,
+ binderThreadTimeMs != 0
+ ? (double) binderThreadTimeMs * 100 / totalThreadTimeMs : 0));
}
}
@@ -11985,8 +12531,10 @@
// So, we distribute total time spent by an uid to different cpu freqs based on the
// amount of time cpu was running at that freq.
final int updatedUidsCount = updatedUids.size();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ final long uptimeMs = mClocks.uptimeMillis();
for (int i = 0; i < updatedUidsCount; ++i) {
- final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
+ final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
final long appCpuTimeUs = updatedUids.valueAt(i);
// Add the cpu speeds to this UID.
final int numClusters = mPowerProfile.getNumCpuClusters();
@@ -12031,6 +12579,7 @@
mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
final long startTimeMs = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> {
long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
@@ -12048,7 +12597,7 @@
mCpuUidUserSysTimeReader.removeUid(uid);
return;
}
- final Uid u = getUidStatsLocked(uid);
+ final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
// Accumulate the total system and user time.
mTempTotalCpuUserTimeUs += userTimeUs;
@@ -12144,6 +12693,7 @@
final int numClusters = mPowerProfile.getNumCpuClusters();
mWakeLockAllocationsUs = null;
final long startTimeMs = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
@@ -12156,7 +12706,7 @@
mCpuUidFreqTimeReader.removeUid(uid);
return;
}
- final Uid u = getUidStatsLocked(uid);
+ final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
detachIfNotNull(u.mCpuFreqTimeMs);
u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
@@ -12257,6 +12807,7 @@
@VisibleForTesting
public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
final long startTimeMs = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
@@ -12269,7 +12820,7 @@
mCpuUidActiveTimeReader.removeUid(uid);
return;
}
- final Uid u = getUidStatsLocked(uid);
+ final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
});
@@ -12286,6 +12837,7 @@
@VisibleForTesting
public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
final long startTimeMs = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
@@ -12298,7 +12850,7 @@
mCpuUidClusterTimeReader.removeUid(uid);
return;
}
- final Uid u = getUidStatsLocked(uid);
+ final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
});
@@ -12338,8 +12890,8 @@
m.arg1 = onBattery ? 1 : 0;
mHandler.sendMessage(m);
- final long uptime = mSecUptime * 1000;
- final long realtime = mSecRealtime * 1000;
+ final long uptimeUs = mSecUptime * 1000;
+ final long realtimeUs = mSecRealtime * 1000;
final int screenState = mScreenState;
if (onBattery) {
// We will reset our status if we are unplugging after the
@@ -12358,14 +12910,14 @@
// stats to be reported in the next checkin. Only do this if we have
// a sufficient amount of data to make it interesting.
if (getLowDischargeAmountSinceCharge() >= 20) {
- final long startTime = SystemClock.uptimeMillis();
+ final long startTimeMs = SystemClock.uptimeMillis();
final Parcel parcel = Parcel.obtain();
writeSummaryToParcel(parcel, true);
- final long initialTime = SystemClock.uptimeMillis() - startTime;
+ final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
BackgroundThread.getHandler().post(new Runnable() {
@Override public void run() {
synchronized (mCheckinFile) {
- final long startTime2 = SystemClock.uptimeMillis();
+ final long startTimeMs2 = SystemClock.uptimeMillis();
FileOutputStream stream = null;
try {
stream = mCheckinFile.startWrite();
@@ -12373,8 +12925,8 @@
stream.flush();
mCheckinFile.finishWrite(stream);
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "batterystats-checkin",
- initialTime + SystemClock.uptimeMillis() - startTime2);
+ "batterystats-checkin", initialTimeMs
+ + SystemClock.uptimeMillis() - startTimeMs2);
} catch (IOException e) {
Slog.w("BatteryStats",
"Error writing checkin battery statistics", e);
@@ -12387,7 +12939,7 @@
});
}
doWrite = true;
- resetAllStatsLocked();
+ resetAllStatsLocked(mSecUptime, mSecRealtime);
if (chargeUAh > 0 && level > 0) {
// Only use the reported coulomb charge value if it is supported and reported.
mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
@@ -12434,7 +12986,7 @@
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenDoze = 0;
mDischargeAmountScreenOff = 0;
- updateTimeBasesLocked(true, screenState, uptime, realtime);
+ updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
} else {
mLastChargingStateLevel = level;
mOnBattery = mOnBatteryInternal = false;
@@ -12450,14 +13002,14 @@
mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
}
updateDischargeScreenLevelsLocked(screenState, screenState);
- updateTimeBasesLocked(false, screenState, uptime, realtime);
+ updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
mChargeStepTracker.init();
mLastChargeStepLevel = level;
mMaxChargeStepLevel = level;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
}
- if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
+ if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
writeAsyncLocked();
}
@@ -12477,18 +13029,18 @@
}
}
- private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
- final long uptimeMs) {
+ private void recordCurrentTimeChangeLocked(final long currentTimeMs,
+ final long elapsedRealtimeMs, final long uptimeMs) {
if (mRecordingHistory) {
- mHistoryCur.currentTime = currentTime;
+ mHistoryCur.currentTime = currentTimeMs;
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
mHistoryCur.currentTime = 0;
}
}
- private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
+ private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
if (mRecordingHistory) {
- mHistoryCur.currentTime = System.currentTimeMillis();
+ mHistoryCur.currentTime = currentTimeMs;
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
mHistoryCur.currentTime = 0;
}
@@ -12507,6 +13059,15 @@
public void setBatteryStateLocked(final int status, final int health, final int plugType,
final int level, /* not final */ int temp, final int volt, final int chargeUAh,
final int chargeFullUAh, final long chargeTimeToFullSeconds) {
+ setBatteryStateLocked(status, health, plugType, level, temp, volt, chargeUAh,
+ chargeFullUAh, chargeTimeToFullSeconds,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
+ }
+
+ public void setBatteryStateLocked(final int status, final int health, final int plugType,
+ final int level, /* not final */ int temp, final int volt, final int chargeUAh,
+ final int chargeFullUAh, final long chargeTimeToFullSeconds,
+ final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
// Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
temp = Math.max(0, temp);
@@ -12514,8 +13075,6 @@
status, plugType, level);
final boolean onBattery = isOnBattery(plugType, status);
- final long uptime = mClocks.uptimeMillis();
- final long elapsedRealtime = mClocks.elapsedRealtime();
if (!mHaveBatteryLevel) {
mHaveBatteryLevel = true;
// We start out assuming that the device is plugged in (not
@@ -12538,20 +13097,20 @@
mLastChargeStepLevel = mLastDischargeStepLevel = level;
mLastChargingStateLevel = level;
} else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
- recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
+ recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
}
int oldStatus = mHistoryCur.batteryStatus;
if (onBattery) {
mDischargeCurrentLevel = level;
if (!mRecordingHistory) {
mRecordingHistory = true;
- startRecordingHistory(elapsedRealtime, uptime, true);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
} else if (level < 96 &&
status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
if (!mRecordingHistory) {
mRecordingHistory = true;
- startRecordingHistory(elapsedRealtime, uptime, true);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
mCurrentBatteryLevel = level;
@@ -12581,7 +13140,7 @@
}
}
mHistoryCur.batteryChargeUAh = chargeUAh;
- setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
+ setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUAh);
} else {
boolean changed = false;
if (mHistoryCur.batteryLevel != level) {
@@ -12641,9 +13200,9 @@
changed |= setChargingLocked(false);
if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
- modeBits, elapsedRealtime);
+ modeBits, elapsedRealtimeMs);
mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
- modeBits, elapsedRealtime);
+ modeBits, elapsedRealtimeMs);
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
mInitStepMode = mCurStepMode;
@@ -12681,9 +13240,9 @@
}
if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
- modeBits, elapsedRealtime);
+ modeBits, elapsedRealtimeMs);
mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
- modeBits, elapsedRealtime);
+ modeBits, elapsedRealtimeMs);
mMaxChargeStepLevel = level;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
@@ -12691,7 +13250,7 @@
mLastChargeStepLevel = level;
}
if (changed) {
- addHistoryRecordLocked(elapsedRealtime, uptime);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
if (!onBattery &&
@@ -12737,7 +13296,7 @@
public long getAwakeTimeBattery() {
// This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
// for over a decade, but surely that was a mistake.
- return getBatteryUptimeLocked();
+ return getBatteryUptimeLocked(mClocks.uptimeMillis());
}
@UnsupportedAppUsage
@@ -12746,35 +13305,35 @@
}
@Override
- public long computeUptime(long curTime, int which) {
- return mUptime + (curTime - mUptimeStart);
+ public long computeUptime(long curTimeUs, int which) {
+ return mUptimeUs + (curTimeUs - mUptimeStartUs);
}
@Override
- public long computeRealtime(long curTime, int which) {
- return mRealtime + (curTime - mRealtimeStart);
+ public long computeRealtime(long curTimeUs, int which) {
+ return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
}
@Override
@UnsupportedAppUsage
- public long computeBatteryUptime(long curTime, int which) {
- return mOnBatteryTimeBase.computeUptime(curTime, which);
+ public long computeBatteryUptime(long curTimeUs, int which) {
+ return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
}
@Override
@UnsupportedAppUsage
- public long computeBatteryRealtime(long curTime, int which) {
- return mOnBatteryTimeBase.computeRealtime(curTime, which);
+ public long computeBatteryRealtime(long curTimeUs, int which) {
+ return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
}
@Override
- public long computeBatteryScreenOffUptime(long curTime, int which) {
- return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
+ public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
+ return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
}
@Override
- public long computeBatteryScreenOffRealtime(long curTime, int which) {
- return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
+ public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
+ return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
}
private long computeTimePerLevel(long[] steps, int numSteps) {
@@ -12877,7 +13436,7 @@
/*@hide */
public CellularBatteryStats getCellularBatteryStats() {
final int which = STATS_SINCE_CHARGED;
- final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+ final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
final ControllerActivityCounter counter = getModemControllerActivity();
final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
@@ -12887,13 +13446,13 @@
counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
for (int i = 0; i < timeInRatMs.length; i++) {
- timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
+ timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
}
long[] timeInRxSignalStrengthLevelMs =
new long[CellSignalStrength.getNumSignalStrengthLevels()];
for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
- timeInRxSignalStrengthLevelMs[i]
- = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
+ timeInRxSignalStrengthLevelMs[i] =
+ getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
}
long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
counter.getTxTimeCounters().length)];
@@ -12903,8 +13462,8 @@
totalTxTimeMs += txTimeMs[i];
}
- return new CellularBatteryStats(computeBatteryRealtime(rawRealTime, which) / 1000,
- getMobileRadioActiveTime(rawRealTime, which) / 1000,
+ return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
+ getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
@@ -12917,7 +13476,7 @@
/*@hide */
public WifiBatteryStats getWifiBatteryStats() {
final int which = STATS_SINCE_CHARGED;
- final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+ final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
final ControllerActivityCounter counter = getWifiControllerActivity();
final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
@@ -12936,19 +13495,19 @@
}
long[] timeInStateMs = new long[NUM_WIFI_STATES];
for (int i=0; i<NUM_WIFI_STATES; i++) {
- timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
+ timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
}
long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
- timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
+ timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
}
long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
- timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
+ timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
}
return new WifiBatteryStats(
- computeBatteryRealtime(rawRealTime, which) / 1000,
- getWifiActiveTime(rawRealTime, which) / 1000,
+ computeBatteryRealtime(rawRealTimeUs, which) / 1000,
+ getWifiActiveTime(rawRealTimeUs, which) / 1000,
getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
@@ -12962,12 +13521,12 @@
public GpsBatteryStats getGpsBatteryStats() {
GpsBatteryStats s = new GpsBatteryStats();
final int which = STATS_SINCE_CHARGED;
- final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
- s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+ final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
+ s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
for (int i=0; i<time.length; i++) {
- time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
+ time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
}
s.setTimeInGpsSignalQualityLevel(time);
return s;
@@ -12988,19 +13547,29 @@
return mDailyPackageChanges;
}
+ /**
+ * @return battery uptime in microseconds
+ */
protected long getBatteryUptimeLocked() {
- return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
+ return getBatteryUptimeLocked(mClocks.uptimeMillis());
+ }
+
+ /**
+ * @return battery uptime in microseconds
+ */
+ protected long getBatteryUptimeLocked(long uptimeMs) {
+ return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
}
@Override
- public long getBatteryUptime(long curTime) {
- return mOnBatteryTimeBase.getUptime(curTime);
+ public long getBatteryUptime(long curTimeUs) {
+ return mOnBatteryTimeBase.getUptime(curTimeUs);
}
@Override
@UnsupportedAppUsage
- public long getBatteryRealtime(long curTime) {
- return mOnBatteryTimeBase.getRealtime(curTime);
+ public long getBatteryRealtime(long curTimeUs) {
+ return mOnBatteryTimeBase.getRealtime(curTimeUs);
}
@Override
@@ -13188,22 +13757,22 @@
return 0;
}
- final long uidTimeAtCpuSpeed = systemUid.getTimeAtCpuSpeed(cluster, step,
+ final long uidTimeAtCpuSpeedUs = systemUid.getTimeAtCpuSpeed(cluster, step,
BatteryStats.STATS_SINCE_CHARGED);
- if (uidTimeAtCpuSpeed == 0) {
+ if (uidTimeAtCpuSpeedUs == 0) {
return 0;
}
- final long uidThreadTime =
+ final long uidThreadTimeUs =
threadTimesForCluster[step].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
- if (uidThreadTime == 0) {
+ if (uidThreadTimeUs == 0) {
return 0;
}
- final long binderThreadTime = mBinderThreadCpuTimesUs[cluster][step].getCountLocked(
+ final long binderThreadTimeUs = mBinderThreadCpuTimesUs[cluster][step].getCountLocked(
BatteryStats.STATS_SINCE_CHARGED);
- return uidTimeAtCpuSpeed * binderThreadTime / uidThreadTime;
+ return uidTimeAtCpuSpeedUs * binderThreadTimeUs / uidThreadTimeUs;
}
/**
@@ -13211,9 +13780,13 @@
*/
@UnsupportedAppUsage
public Uid getUidStatsLocked(int uid) {
+ return getUidStatsLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
Uid u = mUidStats.get(uid);
if (u == null) {
- u = new Uid(this, uid);
+ u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
mUidStats.put(uid, u);
}
return u;
@@ -13229,10 +13802,14 @@
}
public void onCleanupUserLocked(int userId) {
+ onCleanupUserLocked(userId, mClocks.elapsedRealtime());
+ }
+
+ public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
final int firstUidForUser = UserHandle.getUid(userId, 0);
final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
mPendingRemovedUids.add(
- new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
+ new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
}
public void onUserRemovedLocked(int userId) {
@@ -13256,12 +13833,19 @@
*/
@UnsupportedAppUsage
public void removeUidStatsLocked(int uid) {
+ removeUidStatsLocked(uid, mClocks.elapsedRealtime());
+ }
+
+ /**
+ * @see #removeUidStatsLocked(int)
+ */
+ public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
final Uid u = mUidStats.get(uid);
if (u != null) {
u.detachFromTimeBase();
}
mUidStats.remove(uid);
- mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
+ mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
}
/**
@@ -13270,8 +13854,16 @@
*/
@UnsupportedAppUsage
public Uid.Proc getProcessStatsLocked(int uid, String name) {
+ return getProcessStatsLocked(uid, name, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see #getProcessStatsLocked(int, String)
+ */
+ public Uid.Proc getProcessStatsLocked(int uid, String name,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
return u.getProcessStatsLocked(name);
}
@@ -13281,8 +13873,16 @@
*/
@UnsupportedAppUsage
public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
+ return getPackageStatsLocked(uid, pkg, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ /**
+ * @see getPackageStatsLocked(int, String)
+ */
+ public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
return u.getPackageStatsLocked(pkg);
}
@@ -13292,13 +13892,19 @@
*/
@UnsupportedAppUsage
public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
+ return getServiceStatsLocked(uid, pkg, name,
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ }
+
+ public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
+ long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
- Uid u = getUidStatsLocked(uid);
+ Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
return u.getServiceStatsLocked(pkg, name);
}
public void shutdownLocked() {
- recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ recordShutdownLocked(System.currentTimeMillis(), mClocks.elapsedRealtime());
writeSyncLocked();
mShuttingDown = true;
}
@@ -13462,7 +14068,7 @@
mNumSingleUidCpuTimeReads = 0;
mNumBatchedSingleUidCpuTimeReads = 0;
- mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
+ mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
}
}
@@ -13471,7 +14077,7 @@
if (oldDelayMillis != newDelayMillis) {
mNumSingleUidCpuTimeReads = 0;
mNumBatchedSingleUidCpuTimeReads = 0;
- mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
+ mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
}
}
@@ -13521,7 +14127,11 @@
@GuardedBy("this")
public void dumpConstantsLocked(PrintWriter pw) {
- mConstants.dumpLocked(pw);
+ final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, " ");
+ iPw.println("BatteryStats constants:");
+ iPw.increaseIndent();
+ mConstants.dumpLocked(iPw);
+ iPw.decreaseIndent();
}
@GuardedBy("this")
@@ -13569,11 +14179,11 @@
Uid uid = mUidStats.get(u);
double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
- long time = 0;
+ long timeUs = 0;
for (int cluster = 0; cluster < mSystemServerThreadCpuTimesUs.length; cluster++) {
int numSpeeds = mSystemServerThreadCpuTimesUs[cluster].length;
for (int speed = 0; speed < numSpeeds; speed++) {
- time += getSystemServiceTimeAtCpuSpeed(cluster, speed)
+ timeUs += getSystemServiceTimeAtCpuSpeed(cluster, speed)
* proportionalSystemServiceUsage;
}
}
@@ -13581,7 +14191,7 @@
pw.print(" ");
pw.print(u);
pw.print(": ");
- pw.println(time);
+ pw.println(timeUs / 1000);
}
}
}
@@ -13616,7 +14226,7 @@
Slog.d(TAG, "writeSummaryToParcel duration ms:"
+ (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
}
- mLastWriteTime = mClocks.elapsedRealtime();
+ mLastWriteTimeMs = mClocks.elapsedRealtime();
writeParcelToFileLocked(p, mStatsFile, sync);
}
@@ -13657,18 +14267,18 @@
mWriteLock.lock();
FileOutputStream fos = null;
try {
- final long startTime = SystemClock.uptimeMillis();
+ final long startTimeMs = SystemClock.uptimeMillis();
fos = file.startWrite();
fos.write(p.marshall());
fos.flush();
file.finishWrite(fos);
if (DEBUG) {
Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
- + " duration ms:" + (SystemClock.uptimeMillis() - startTime)
+ + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
+ " bytes:" + p.dataSize());
}
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "batterystats", SystemClock.uptimeMillis() - startTime);
+ "batterystats", SystemClock.uptimeMillis() - startTimeMs);
} catch (IOException e) {
Slog.w(TAG, "Error writing battery statistics", e);
file.failWrite(fos);
@@ -13714,7 +14324,7 @@
}
} catch (Exception e) {
Slog.e(TAG, "Error reading battery statistics", e);
- resetAllStatsLocked();
+ resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime());
} finally {
stats.recycle();
}
@@ -13749,16 +14359,17 @@
if (mHistoryBuffer.dataPosition() > 0
|| mBatteryStatsHistory.getFilesNumbers().size() > 1) {
mRecordingHistory = true;
- final long elapsedRealtime = mClocks.elapsedRealtime();
- final long uptime = mClocks.uptimeMillis();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ final long uptimeMs = mClocks.uptimeMillis();
if (USE_OLD_HISTORY) {
- addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
+ addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.CMD_START, mHistoryCur);
}
- addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
- startRecordingHistory(elapsedRealtime, uptime, false);
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
}
- recordDailyStatsIfNeededLocked(false);
+ recordDailyStatsIfNeededLocked(false, System.currentTimeMillis());
}
public int describeContents() {
@@ -13799,27 +14410,27 @@
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
- sb.append("****************** OLD mHistoryBaseTime: ");
- TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ sb.append("****************** OLD mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
Slog.i(TAG, sb.toString());
}
- mHistoryBaseTime = historyBaseTime;
+ mHistoryBaseTimeMs = historyBaseTime;
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
- sb.append("****************** NEW mHistoryBaseTime: ");
- TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ sb.append("****************** NEW mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
Slog.i(TAG, sb.toString());
}
// We are just arbitrarily going to insert 1 minute from the sample of
// the last run until samples in this run.
- if (mHistoryBaseTime > 0) {
+ if (mHistoryBaseTimeMs > 0) {
long oldnow = mClocks.elapsedRealtime();
- mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
+ mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
- sb.append("****************** ADJUSTED mHistoryBaseTime: ");
- TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
Slog.i(TAG, sb.toString());
}
}
@@ -13839,14 +14450,14 @@
void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
- sb.append("****************** WRITING mHistoryBaseTime: ");
- TimeUtils.formatDuration(mHistoryBaseTime, sb);
- sb.append(" mLastHistoryElapsedRealtime: ");
- TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
+ sb.append("****************** WRITING mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ sb.append(" mLastHistoryElapsedRealtimeMs: ");
+ TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
Slog.i(TAG, sb.toString());
}
out.writeInt(VERSION);
- out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
+ out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
if (!inclData) {
out.writeInt(0);
out.writeInt(0);
@@ -13913,9 +14524,9 @@
}
mStartCount = in.readInt();
- mUptime = in.readLong();
- mRealtime = in.readLong();
- mStartClockTime = in.readLong();
+ mUptimeUs = in.readLong();
+ mRealtimeUs = in.readLong();
+ mStartClockTimeMs = in.readLong();
mStartPlatformVersion = in.readString();
mEndPlatformVersion = in.readString();
mOnBatteryTimeBase.readSummaryFromParcel(in);
@@ -13955,9 +14566,9 @@
} else {
mDailyPackageChanges = null;
}
- mDailyStartTime = in.readLong();
- mNextMinDailyDeadline = in.readLong();
- mNextMaxDailyDeadline = in.readLong();
+ mDailyStartTimeMs = in.readLong();
+ mNextMinDailyDeadlineMs = in.readLong();
+ mNextMaxDailyDeadlineMs = in.readLong();
mStartCount++;
@@ -13971,8 +14582,8 @@
mInteractiveTimer.readSummaryFromParcelLocked(in);
mPhoneOn = false;
mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
- mLongestLightIdleTime = in.readLong();
- mLongestFullIdleTime = in.readLong();
+ mLongestLightIdleTimeMs = in.readLong();
+ mLongestFullIdleTimeMs = in.readLong();
mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
@@ -14084,9 +14695,11 @@
if (NU > 10000) {
throw new ParcelFormatException("File corrupt: too many uids " + NU);
}
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ final long uptimeMs = mClocks.uptimeMillis();
for (int iu = 0; iu < NU; iu++) {
int uid = in.readInt();
- Uid u = new Uid(this, uid);
+ Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
mUidStats.put(uid, u);
u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
@@ -14329,9 +14942,9 @@
for (int ip = 0; ip < NP; ip++) {
String procName = in.readString();
Uid.Proc p = u.getProcessStatsLocked(procName);
- p.mUserTime = in.readLong();
- p.mSystemTime = in.readLong();
- p.mForegroundTime = in.readLong();
+ p.mUserTimeMs = in.readLong();
+ p.mSystemTimeMs = in.readLong();
+ p.mForegroundTimeMs = in.readLong();
p.mStarts = in.readInt();
p.mNumCrashes = in.readInt();
p.mNumAnrs = in.readInt();
@@ -14364,7 +14977,7 @@
for (int is = 0; is < NS; is++) {
String servName = in.readString();
Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
- s.mStartTime = in.readLong();
+ s.mStartTimeMs = in.readLong();
s.mStarts = in.readInt();
s.mLaunches = in.readInt();
}
@@ -14407,7 +15020,7 @@
out.writeInt(mStartCount);
out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
- out.writeLong(mStartClockTime);
+ out.writeLong(mStartClockTimeMs);
out.writeString(mStartPlatformVersion);
out.writeString(mEndPlatformVersion);
mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
@@ -14445,9 +15058,9 @@
} else {
out.writeInt(0);
}
- out.writeLong(mDailyStartTime);
- out.writeLong(mNextMinDailyDeadline);
- out.writeLong(mNextMaxDailyDeadline);
+ out.writeLong(mDailyStartTimeMs);
+ out.writeLong(mNextMinDailyDeadlineMs);
+ out.writeLong(mNextMaxDailyDeadlineMs);
mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -14456,8 +15069,8 @@
}
mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
- out.writeLong(mLongestLightIdleTime);
- out.writeLong(mLongestFullIdleTime);
+ out.writeLong(mLongestLightIdleTimeMs);
+ out.writeLong(mLongestFullIdleTimeMs);
mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -14852,9 +15465,9 @@
for (int ip=0; ip<NP; ip++) {
out.writeString(u.mProcessStats.keyAt(ip));
Uid.Proc ps = u.mProcessStats.valueAt(ip);
- out.writeLong(ps.mUserTime);
- out.writeLong(ps.mSystemTime);
- out.writeLong(ps.mForegroundTime);
+ out.writeLong(ps.mUserTimeMs);
+ out.writeLong(ps.mSystemTimeMs);
+ out.writeLong(ps.mForegroundTimeMs);
out.writeInt(ps.mStarts);
out.writeInt(ps.mNumCrashes);
out.writeInt(ps.mNumAnrs);
@@ -14880,7 +15493,7 @@
out.writeString(ps.mServiceStats.keyAt(is));
BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
long time = ss.getStartTimeToNowLocked(
- mOnBatteryTimeBase.getUptime(NOW_SYS));
+ mOnBatteryTimeBase.getUptime(NOW_SYS) / 1000);
out.writeLong(time);
out.writeInt(ss.mStarts);
out.writeInt(ss.mLaunches);
@@ -14904,13 +15517,13 @@
mBatteryStatsHistory.readFromParcel(in);
mStartCount = in.readInt();
- mStartClockTime = in.readLong();
+ mStartClockTimeMs = in.readLong();
mStartPlatformVersion = in.readString();
mEndPlatformVersion = in.readString();
- mUptime = in.readLong();
- mUptimeStart = in.readLong();
- mRealtime = in.readLong();
- mRealtimeStart = in.readLong();
+ mUptimeUs = in.readLong();
+ mUptimeStartUs = in.readLong();
+ mRealtimeUs = in.readLong();
+ mRealtimeStartUs = in.readLong();
mOnBattery = in.readInt() != 0;
mEstimatedBatteryCapacity = in.readInt();
mMinLearnedBatteryCapacity = in.readInt();
@@ -14931,8 +15544,8 @@
mPhoneOn = false;
mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
mOnBatteryTimeBase, in);
- mLongestLightIdleTime = in.readLong();
- mLongestFullIdleTime = in.readLong();
+ mLongestLightIdleTimeMs = in.readLong();
+ mLongestFullIdleTimeMs = in.readLong();
mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
mOnBatteryTimeBase, in);
mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
@@ -15030,7 +15643,7 @@
mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
- mLastWriteTime = in.readLong();
+ mLastWriteTimeMs = in.readLong();
mRpmStats.clear();
int NRPMS = in.readInt();
@@ -15096,9 +15709,11 @@
int numUids = in.readInt();
mUidStats.clear();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+ final long uptimeMs = mClocks.uptimeMillis();
for (int i = 0; i < numUids; i++) {
int uid = in.readInt();
- Uid u = new Uid(this, uid);
+ Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
mUidStats.append(uid, u);
}
@@ -15137,13 +15752,13 @@
mBatteryStatsHistory.writeToParcel(out);
out.writeInt(mStartCount);
- out.writeLong(mStartClockTime);
+ out.writeLong(mStartClockTimeMs);
out.writeString(mStartPlatformVersion);
out.writeString(mEndPlatformVersion);
- out.writeLong(mUptime);
- out.writeLong(mUptimeStart);
- out.writeLong(mRealtime);
- out.writeLong(mRealtimeStart);
+ out.writeLong(mUptimeUs);
+ out.writeLong(mUptimeStartUs);
+ out.writeLong(mRealtimeUs);
+ out.writeLong(mRealtimeStartUs);
out.writeInt(mOnBattery ? 1 : 0);
out.writeInt(mEstimatedBatteryCapacity);
out.writeInt(mMinLearnedBatteryCapacity);
@@ -15158,8 +15773,8 @@
}
mInteractiveTimer.writeToParcel(out, uSecRealtime);
mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
- out.writeLong(mLongestLightIdleTime);
- out.writeLong(mLongestFullIdleTime);
+ out.writeLong(mLongestLightIdleTimeMs);
+ out.writeLong(mLongestFullIdleTimeMs);
mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
@@ -15227,7 +15842,7 @@
mDischargeScreenDozeCounter.writeToParcel(out);
mDischargeLightDozeCounter.writeToParcel(out);
mDischargeDeepDozeCounter.writeToParcel(out);
- out.writeLong(mLastWriteTime);
+ out.writeLong(mLastWriteTimeMs);
out.writeInt(mRpmStats.size());
for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
@@ -15467,15 +16082,19 @@
mCameraOnTimer.logState(pr, " ");
}
super.dumpLocked(context, pw, flags, reqUid, histStart);
+
pw.print("Total cpu time reads: ");
pw.println(mNumSingleUidCpuTimeReads);
pw.print("Batched cpu time reads: ");
pw.println(mNumBatchedSingleUidCpuTimeReads);
pw.print("Batching Duration (min): ");
- pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
+ pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
pw.print("All UID cpu time reads since the later of device start or stats reset: ");
pw.println(mNumAllUidCpuTimeReads);
pw.print("UIDs removed since the later of device start or stats reset: ");
pw.println(mNumUidsRemoved);
+
+ pw.println();
+ dumpConstantsLocked(pw);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 32e7fdc..5948e7e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -86,9 +86,10 @@
*/
public class ZygoteInit {
- // TODO (chriswailes): Change this so it is set with Zygote or ZygoteSecondary as appropriate
private static final String TAG = "Zygote";
+ private static final boolean LOGGING_DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
private static final String PROPERTY_DISABLE_GRAPHICS_DRIVER_PRELOADING =
"ro.zygote.disable_gl_preload";
@@ -284,6 +285,7 @@
new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);
int count = 0;
+ int missingLambdaCount = 0;
String line;
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
@@ -302,24 +304,33 @@
Class.forName(line, true, null);
count++;
} catch (ClassNotFoundException e) {
- Log.w(TAG, "Class not found for preloading: " + line);
+ if (line.contains("$$Lambda$")) {
+ if (LOGGING_DEBUG) {
+ missingLambdaCount++;
+ }
+ } else {
+ Log.w(TAG, "Class not found for preloading: " + line);
+ }
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
- }
- if (t instanceof RuntimeException) {
+ } else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
+ } else {
+ throw new RuntimeException(t);
}
- throw new RuntimeException(t);
}
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
}
Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
+ if (LOGGING_DEBUG && missingLambdaCount != 0) {
+ Log.i(TAG, "Unresolved lambda preloads: " + missingLambdaCount);
+ }
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 7f3eb45..d5f54a1 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -18,13 +18,11 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
-import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
-import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IScrollCaptureController;
import android.view.IWindow;
@@ -33,6 +31,7 @@
import android.view.InsetsState;
import android.view.PointerIcon;
import android.view.WindowInsets.Type.InsetsType;
+import android.window.ClientWindowFrames;
import com.android.internal.os.IResultReceiver;
@@ -51,11 +50,9 @@
}
@Override
- public void resized(Rect frame, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, boolean reportDraw,
- MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
if (reportDraw) {
try {
mSession.finishDrawing(this, null /* postDrawTransaction */);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index c51f334..c08363b 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -19,18 +19,16 @@
// To make sure cpu_set_t is included from sched.h
#define _GNU_SOURCE 1
-#include <android-base/properties.h>
-#include <android-base/unique_fd.h>
-#include <binder/ActivityManager.h>
+#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
#include <meminfo/procmeminfo.h>
#include <meminfo/sysmeminfo.h>
#include <processgroup/processgroup.h>
#include <processgroup/sched_policy.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
+#include <android-base/unique_fd.h>
#include <algorithm>
#include <array>
@@ -86,8 +84,6 @@
static pthread_key_t gBgKey = -1;
#endif
-static bool boot_completed = false;
-
// For both of these, err should be in the errno range (positive), not a status_t (negative)
static void signalExceptionForError(JNIEnv* env, int err, int tid) {
switch (err) {
@@ -584,20 +580,7 @@
}
#endif
- SchedPolicy policy;
- bool policy_changed = false;
- int rc = 0, curr_pri = getpriority(PRIO_PROCESS, pid);
-
- if (pri == curr_pri) {
- return;
- }
-
- if (!boot_completed) {
- boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
- }
-
- // Do not change sched policy cgroup after boot complete.
- rc = androidSetThreadPriorityAndPolicy(pid, pri, !boot_completed);
+ int rc = androidSetThreadPriority(pid, pri);
if (rc != 0) {
if (rc == INVALID_OPERATION) {
signalExceptionForPriorityError(env, errno, pid);
@@ -606,31 +589,6 @@
}
}
- // Only use async approach after boot complete.
- if (!boot_completed) {
- return;
- }
-
- // Change to background sched policy for the thread if setting to low priority.
- if (pri >= ANDROID_PRIORITY_BACKGROUND) {
- policy = SP_BACKGROUND;
- policy_changed = true;
- // Change to sched policy of the process if thread priority is raising from low priority.
- } else if (curr_pri >= ANDROID_PRIORITY_BACKGROUND) {
- // If we cannot get sched policy of the process, use SP_FOREGROUND as default.
- policy = SP_FOREGROUND;
- get_sched_policy(getpid(), &policy);
- policy_changed = true;
- }
-
- // Sched policy will only change in above 2 cases.
- if (policy_changed) {
- ActivityManager am;
- if (!am.setSchedPolicyCgroup(pid, policy)) {
- ALOGE("am.setThreadPriority failed: tid=%d priority=%d policy=%d", pid, pri, policy);
- }
- }
-
//ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n",
// pid, pri, getpriority(PRIO_PROCESS, pid));
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 416f837..4ef15d7 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -30,7 +30,6 @@
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_view_SurfaceSession.h>
-#include <gui/IScreenCaptureListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -189,11 +188,6 @@
static struct {
jclass clazz;
- jmethodID onScreenCaptureComplete;
-} gScreenCaptureListenerClassInfo;
-
-static struct {
- jclass clazz;
jmethodID ctor;
jfieldID defaultConfig;
jfieldID primaryRefreshRateMin;
@@ -232,54 +226,6 @@
}
}
-class ScreenCaptureListenerWrapper : public BnScreenCaptureListener {
-public:
- explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) {
- env->GetJavaVM(&mVm);
- screenCaptureListenerObject = env->NewGlobalRef(jobject);
- LOG_ALWAYS_FATAL_IF(!screenCaptureListenerObject, "Failed to make global ref");
- }
-
- ~ScreenCaptureListenerWrapper() {
- if (screenCaptureListenerObject) {
- getenv()->DeleteGlobalRef(screenCaptureListenerObject);
- screenCaptureListenerObject = nullptr;
- }
- }
-
- status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) {
- JNIEnv* env = getenv();
- if (captureResults.result != NO_ERROR || captureResults.buffer == nullptr) {
- env->CallVoidMethod(screenCaptureListenerObject,
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete, nullptr);
- return NO_ERROR;
- }
- jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
- env, captureResults.buffer->toAHardwareBuffer());
- const jint namedColorSpace =
- fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
- jobject screenshotHardwareBuffer =
- env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
- gScreenshotHardwareBufferClassInfo.builder,
- jhardwareBuffer, namedColorSpace,
- captureResults.capturedSecureLayers);
- env->CallVoidMethod(screenCaptureListenerObject,
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete,
- screenshotHardwareBuffer);
- return NO_ERROR;
- }
-
-private:
- jobject screenCaptureListenerObject;
- JavaVM* mVm;
-
- JNIEnv* getenv() {
- JNIEnv* env;
- mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
- return env;
- }
-};
-
// ----------------------------------------------------------------------------
static jlong nativeCreateTransaction(JNIEnv* env, jclass clazz) {
@@ -381,28 +327,36 @@
return captureArgs;
}
-static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject,
- jobject screenCaptureListenerObject) {
+static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject) {
const DisplayCaptureArgs captureArgs =
displayCaptureArgsFromObject(env, displayCaptureArgsObject);
if (captureArgs.displayToken == NULL) {
- return BAD_VALUE;
+ return NULL;
}
- sp<IScreenCaptureListener> captureListener =
- new ScreenCaptureListenerWrapper(env, screenCaptureListenerObject);
- return ScreenshotClient::captureDisplay(captureArgs, captureListener);
+ ScreenCaptureResults captureResults;
+ status_t res = ScreenshotClient::captureDisplay(captureArgs, captureResults);
+ if (res != NO_ERROR) {
+ return NULL;
+ }
+
+ jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
+ env, captureResults.buffer->toAHardwareBuffer());
+ const jint namedColorSpace =
+ fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
+ return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
+ gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer,
+ namedColorSpace, captureResults.capturedSecureLayers);
}
-static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject,
- jobject screenCaptureListenerObject) {
+static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject) {
LayerCaptureArgs captureArgs;
getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
if (layer == nullptr) {
- return BAD_VALUE;
+ return nullptr;
}
captureArgs.layerHandle = layer->getHandle();
@@ -426,9 +380,19 @@
env->ReleaseLongArrayElements(excludeObjectArray, const_cast<jlong*>(objects), JNI_ABORT);
}
- sp<IScreenCaptureListener> captureListener =
- new ScreenCaptureListenerWrapper(env, screenCaptureListenerObject);
- return ScreenshotClient::captureLayers(captureArgs, captureListener);
+ ScreenCaptureResults captureResults;
+ status_t res = ScreenshotClient::captureLayers(captureArgs, captureResults);
+ if (res != NO_ERROR) {
+ return NULL;
+ }
+
+ jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
+ env, captureResults.buffer->toAHardwareBuffer());
+ const jint namedColorSpace =
+ fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
+ return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
+ gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer,
+ namedColorSpace, captureResults.capturedSecureLayers);
}
static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) {
@@ -1541,10 +1505,24 @@
return reinterpret_cast<jlong>(surfaceControl->getHandle().get());
}
+static void nativeSetFocusedWindow(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jobject toTokenObj, jobject focusedTokenObj, jint displayId) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ if (toTokenObj == NULL) return;
+
+ sp<IBinder> toToken(ibinderForJavaObject(env, toTokenObj));
+ sp<IBinder> focusedToken;
+ if (focusedTokenObj != NULL) {
+ focusedToken = ibinderForJavaObject(env, focusedTokenObj);
+ }
+ transaction->setFocusedWindow(toToken, focusedToken, systemTime(SYSTEM_TIME_MONOTONIC),
+ displayId);
+}
+
// ----------------------------------------------------------------------------
-// clang-format off
static const JNINativeMethod sSurfaceControlMethods[] = {
+ // clang-format off
{"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJLandroid/os/Parcel;)J",
(void*)nativeCreate },
{"nativeReadFromParcel", "(Landroid/os/Parcel;)J",
@@ -1686,10 +1664,12 @@
{"nativeSetOverrideScalingMode", "(JJI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeCaptureDisplay",
- "(Landroid/view/SurfaceControl$DisplayCaptureArgs;Landroid/view/SurfaceControl$ScreenCaptureListener;)I",
+ "(Landroid/view/SurfaceControl$DisplayCaptureArgs;)"
+ "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
(void*)nativeCaptureDisplay },
{"nativeCaptureLayers",
- "(Landroid/view/SurfaceControl$LayerCaptureArgs;Landroid/view/SurfaceControl$ScreenCaptureListener;)I",
+ "(Landroid/view/SurfaceControl$LayerCaptureArgs;)"
+ "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
(void*)nativeCaptureLayers },
{"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
(void*)nativeSetInputWindowInfo },
@@ -1721,9 +1701,12 @@
(void*)nativeSetGlobalShadowSettings },
{"nativeGetHandle", "(J)J",
(void*)nativeGetHandle },
- {"nativeSetFixedTransformHint", "(JJI)V", (void*)nativeSetFixedTransformHint},
+ {"nativeSetFixedTransformHint", "(JJI)V",
+ (void*)nativeSetFixedTransformHint},
+ {"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Landroid/os/IBinder;I)V",
+ (void*)nativeSetFocusedWindow},
+ // clang-format on
};
-// clang-format on
int register_android_view_SurfaceControl(JNIEnv* env)
{
@@ -1892,12 +1875,6 @@
gLayerCaptureArgsClassInfo.childrenOnly =
GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");
- jclass screenCaptureListenerClazz =
- FindClassOrDie(env, "android/view/SurfaceControl$ScreenCaptureListener");
- gScreenCaptureListenerClassInfo.clazz = MakeGlobalRefOrDie(env, screenCaptureListenerClazz);
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete =
- GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete",
- "(Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;)V");
return err;
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 3d12d07..7f743ef 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -219,6 +219,8 @@
optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto force_bold_text = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
message Gesture {
optional SettingProto aware_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -615,5 +617,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 85;
+ // Next tag = 86;
}
diff --git a/core/proto/android/wifi/enums.proto b/core/proto/android/wifi/enums.proto
index 315c579..e676fef 100644
--- a/core/proto/android/wifi/enums.proto
+++ b/core/proto/android/wifi/enums.proto
@@ -48,3 +48,65 @@
*/
WIFI_MODE_FULL_LOW_LATENCY = 4;
}
+
+/**
+ * Wifi authentication type.
+ */
+enum WifiAuthType {
+ AUTH_TYPE_NONE = 0;
+
+ // WPA pre-shared key.
+ AUTH_TYPE_WPA_PSK = 1;
+ // WPA using EAP authentication. Generally used with an external authentication server.
+ AUTH_TYPE_WPA_EAP = 2;
+ // IEEE 802.1X using EAP authentication and (optionally) dynamically generated WEP keys.
+ AUTH_TYPE_IEEE8021X = 3;
+ // WPA2 pre-shared key for use with soft access point.
+ AUTH_TYPE_WPA2_PSK = 4;
+ // Hotspot 2.0 r2 OSEN.
+ AUTH_TYPE_OSEN = 5;
+ // IEEE 802.11r Fast BSS Transition with PSK authentication.
+ AUTH_TYPE_FT_PSK = 6;
+ // IEEE 802.11r Fast BSS Transition with EAP authentication.
+ AUTH_TYPE_FT_EAP = 7;
+ // Simultaneous Authentication of Equals.
+ AUTH_TYPE_SAE = 8;
+ // Opportunistic Wireless Encryption.
+ AUTH_TYPE_OWE = 9;
+ // SUITE_B_192 192 bit level
+ AUTH_TYPE_SUITE_B_192 = 10;
+ // WPA pre-shared key with stronger SHA256-based algorithms.
+ AUTH_TYPE_WPA_PSK_SHA256 = 11;
+ // WPA using EAP authentication with stronger SHA256-based algorithms.
+ AUTH_TYPE_WPA_EAP_SHA256 = 12;
+ // WAPI pre-shared key.
+ AUTH_TYPE_WAPI_PSK = 13;
+ // WAPI certificate to be specified.
+ AUTH_TYPE_WAPI_CERT = 14;
+ // IEEE 802.11ai FILS SK with SHA256.
+ AUTH_TYPE_FILS_SHA256 = 15;
+ // IEEE 802.11ai FILS SK with SHA384.
+ AUTH_TYPE_FILS_SHA384 = 16;
+}
+
+/**
+ * Bucketed wifi band.
+ */
+enum WifiBandBucket {
+ BAND_UNKNOWN = 0;
+
+ // All of 2.4GHz band
+ BAND_2G = 1;
+ // Frequencies in the range of [5150, 5250) GHz
+ BAND_5G_LOW = 2;
+ // Frequencies in the range of [5250, 5725) GHz
+ BAND_5G_MIDDLE = 3;
+ // Frequencies in the range of [5725, 5850) GHz
+ BAND_5G_HIGH = 4;
+ // Frequencies in the range of [5925, 6425) GHz
+ BAND_6G_LOW = 5;
+ // Frequencies in the range of [6425, 6875) GHz
+ BAND_6G_MIDDLE = 6;
+ // Frequencies in the range of [6875, 7125) GHz
+ BAND_6G_HIGH = 7;
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cdcb24b..560e3c1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4691,6 +4691,12 @@
<permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows the holder to send category_car notifications.
+ @hide -->
+ <permission
+ android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"
+ android:protectionLevel="signature|privileged" />
+
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
@@ -5496,6 +5502,10 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
+ <service android:name="com.android.server.profcollect.ProfcollectForwardingService$ProfcollectBGJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
<service
android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b6f6627..d0d7eca 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -272,9 +272,9 @@
<string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"وضع صامت"</string>
<string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"الصوت متوقف"</string>
<string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"الصوت قيد التفعيل"</string>
- <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"وضع الطائرة"</string>
- <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"وضع الطائرة قيد التفعيل"</string>
- <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"وضع الطائرة متوقف"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"وضع الطيران"</string>
+ <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"وضع الطيران قيد التفعيل"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"وضع الطيران متوقف"</string>
<string name="global_action_settings" msgid="4671878836947494217">"الإعدادات"</string>
<string name="global_action_assist" msgid="2517047220311505805">"مساعدة"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"المساعد الصوتي"</string>
@@ -2156,7 +2156,7 @@
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"جدول بيانات: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_presentation" msgid="1145384236788242075">"عرض تقديمي"</string>
<string name="mime_type_presentation_ext" msgid="8761049335564371468">"عرض تقديمي: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
- <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"سيظل البلوتوث مفعَّلاً أثناء استخدام \"وضع الطائرة\"."</string>
+ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"سيظل البلوتوث مفعَّلاً أثناء استخدام \"وضع الطيران\"."</string>
<string name="car_loading_profile" msgid="8219978381196748070">"جارٍ التحميل"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="zero"><xliff:g id="FILE_NAME_2">%s</xliff:g> و<xliff:g id="COUNT_3">%d</xliff:g> ملف</item>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index feef587..755ee47 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -973,7 +973,7 @@
<string name="save_password_remember" msgid="6490888932657708341">"Zapamti"</string>
<string name="save_password_never" msgid="6776808375903410659">"Nikad"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"Nemate odobrenje za otvaranje ove stranice."</string>
- <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međuspremnik."</string>
+ <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međumemoriju."</string>
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="more_item_label" msgid="7419249600215749115">"Više"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 84f3243..2308b5a 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -423,7 +423,7 @@
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Esta app puede agregar, quitar o cambiar eventos del calendario en tu teléfono. Puede enviar mensajes que parecen proceder de propietarios del calendario o cambiar eventos sin notificarlos."</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acceder a comandos adicionales del proveedor del lugar"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
- <string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación exacta solo en primer plano"</string>
+ <string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación precisa solo en primer plano"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Mientras la usas, esta app puede obtener tu ubicación exacta mediante los Servicios de ubicación, siempre y cuando el dispositivo los tenga activados. Es posible que esto aumente el uso de batería."</string>
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acceder a la ubicación aproximada solo en primer plano"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Mientras la usas, esta app puede obtener tu ubicación aproximada mediante los Servicios de ubicación, siempre y cuando el dispositivo los tenga activados."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9062435..3b44295 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -309,7 +309,7 @@
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"hanganyag rögzítése"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Testmozgás"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"hozzáférés a testmozgási adatokhoz"</string>
- <string name="permgrouplab_camera" msgid="9090413408963547706">"Fényképezőgép"</string>
+ <string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotók és videók készítése"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Hívásnaplók"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"hívásnapló olvasása és írása"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 671863d..162b4d3 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1320,7 +1320,7 @@
<string name="console_running_notification_title" msgid="6087888939261635904">"Сериялык консоль иштетилди"</string>
<string name="console_running_notification_message" msgid="7892751888125174039">"Майнаптуулугуна таасири тиет. Аны өчүрүү үчүн операциялык тутумду жүктөгүчтү текшериңиз."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"USB портунда суюктук же урандылар бар"</string>
- <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчүрүлдү. Кененирээк маалымат алуу үчүн, таптап коюңуз."</string>
+ <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчтү. Кененирээк маалымат алуу үчүн, таптап коюңуз."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB портун колдонууга болот"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"Телефон суюктук менен урандыларды аныктаган жок."</string>
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f63e647..95f7439 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1279,7 +1279,7 @@
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Nooit toestaan"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"Simkaart verwijderd"</string>
<string name="sim_removed_message" msgid="9051174064474904617">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
- <string name="sim_done_button" msgid="6464250841528410598">"Gereed"</string>
+ <string name="sim_done_button" msgid="6464250841528410598">"Klaar"</string>
<string name="sim_added_title" msgid="7930779986759414595">"Simkaart aangesloten"</string>
<string name="sim_added_message" msgid="6602906609509958680">"Start je apparaat opnieuw voor toegang tot het mobiele netwerk."</string>
<string name="sim_restart_button" msgid="8481803851341190038">"Opnieuw starten"</string>
@@ -1292,7 +1292,7 @@
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Tijd instellen"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Datum instellen"</string>
<string name="date_time_set" msgid="4603445265164486816">"Instellen"</string>
- <string name="date_time_done" msgid="8363155889402873463">"Gereed"</string>
+ <string name="date_time_done" msgid="8363155889402873463">"Klaar"</string>
<string name="perms_new_perm_prefix" msgid="6984556020395757087"><font size="12" fgcolor="#ff33b5e5">"NIEUW: "</font></string>
<string name="perms_description_app" msgid="2747752389870161996">"Geleverd door <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="no_permissions" msgid="5729199278862516390">"Geen rechten nodig"</string>
@@ -1379,7 +1379,7 @@
<string name="ext_media_status_removed" msgid="241223931135751691">"Verwijderd"</string>
<string name="ext_media_status_unmounted" msgid="8145812017295835941">"Uitgeworpen"</string>
<string name="ext_media_status_checking" msgid="159013362442090347">"Controleren…"</string>
- <string name="ext_media_status_mounted" msgid="3459448555811203459">"Gereed"</string>
+ <string name="ext_media_status_mounted" msgid="3459448555811203459">"Klaar"</string>
<string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"Alleen lezen"</string>
<string name="ext_media_status_bad_removal" msgid="508448566481406245">"Onveilig verwijderd"</string>
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"Beschadigd"</string>
@@ -1404,7 +1404,7 @@
<string name="ime_action_search" msgid="4501435960587287668">"Zoeken"</string>
<string name="ime_action_send" msgid="8456843745664334138">"Verzenden"</string>
<string name="ime_action_next" msgid="4169702997635728543">"Volgende"</string>
- <string name="ime_action_done" msgid="6299921014822891569">"Gereed"</string>
+ <string name="ime_action_done" msgid="6299921014822891569">"Klaar"</string>
<string name="ime_action_previous" msgid="6548799326860401611">"Vorige"</string>
<string name="ime_action_default" msgid="8265027027659800121">"Uitvoeren"</string>
<string name="dial_number_using" msgid="6060769078933953531">"Nummer bellen\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1451,7 +1451,7 @@
<item quantity="other"><xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g></item>
<item quantity="one">1 overeenkomst</item>
</plurals>
- <string name="action_mode_done" msgid="2536182504764803222">"Gereed"</string>
+ <string name="action_mode_done" msgid="2536182504764803222">"Klaar"</string>
<string name="progress_erasing" msgid="6891435992721028004">"Gedeelde opslag wissen…"</string>
<string name="share" msgid="4157615043345227321">"Delen"</string>
<string name="find" msgid="5015737188624767706">"Vinden"</string>
@@ -1492,7 +1492,7 @@
<string name="keyboardview_keycode_alt" msgid="8997420058584292385">"Alt"</string>
<string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"Annuleren"</string>
<string name="keyboardview_keycode_delete" msgid="2661117313730098650">"Delete"</string>
- <string name="keyboardview_keycode_done" msgid="2524518019001653851">"Gereed"</string>
+ <string name="keyboardview_keycode_done" msgid="2524518019001653851">"Klaar"</string>
<string name="keyboardview_keycode_mode_change" msgid="2743735349997999020">"Modus wijzigen"</string>
<string name="keyboardview_keycode_shift" msgid="3026509237043975573">"Shift"</string>
<string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
@@ -1645,7 +1645,7 @@
<string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Functies kiezen voor gebruik met de sneltoets via de volumeknop"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is uitgeschakeld"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
- <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gereed"</string>
+ <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitschakelen"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string>
@@ -1774,7 +1774,7 @@
<string name="immersive_cling_title" msgid="2307034298721541791">"Volledig scherm wordt weergegeven"</string>
<string name="immersive_cling_description" msgid="7092737175345204832">"Swipe omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ik snap het"</string>
- <string name="done_label" msgid="7283767013231718521">"Gereed"</string>
+ <string name="done_label" msgid="7283767013231718521">"Klaar"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ronde schuifregelaar voor uren"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Ronde schuifregelaar voor minuten"</string>
<string name="select_hours" msgid="5982889657313147347">"Uren selecteren"</string>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index e17c312..6ae6faa 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -50,6 +50,7 @@
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
+ <uses-permission android:name="android.permission.DEVICE_POWER"/>
<uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 0490678..88faa0a 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -574,16 +574,16 @@
InstallParams(String outFileName, int rawResId) throws PackageParserException {
this.pkg = getParsedPackage(outFileName, rawResId);
- this.packageURI = Uri.fromFile(new File(pkg.getCodePath()));
+ this.packageURI = Uri.fromFile(new File(pkg.getPath()));
}
InstallParams(ParsingPackage pkg) {
- this.packageURI = Uri.fromFile(new File(pkg.getCodePath()));
+ this.packageURI = Uri.fromFile(new File(pkg.getPath()));
this.pkg = pkg;
}
long getApkSize() {
- File file = new File(pkg.getCodePath());
+ File file = new File(pkg.getPath());
return file.length();
}
}
@@ -1003,7 +1003,7 @@
try {
cleanUpInstall(ip.pkg.getPackageName());
} finally {
- File outFile = new File(ip.pkg.getCodePath());
+ File outFile = new File(ip.pkg.getPath());
if (outFile != null && outFile.exists()) {
outFile.delete();
}
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
index fbf75df..a01459f 100644
--- a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
@@ -146,7 +146,7 @@
when(a.getTargetSdkVersion()).thenReturn(info.targetSdkVersion);
when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
when(a.getOverlayPriority()).thenReturn(info.priority);
- when(a.getBaseCodePath()).thenReturn(info.path.getPath());
+ when(a.getBaseApkPath()).thenReturn(info.path.getPath());
f.accept(a, !info.path.getPath().contains("data/overlay"));
}
return null;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java
new file mode 100644
index 0000000..e870d60
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.Build;
+import android.os.ConditionVariable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import com.google.android.collect.Sets;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class BatteryInputSuspendTest {
+
+ public static final Set<String> SUPPORTED_DEVICES = Sets.newArraySet(
+ "blueline",
+ "crosshatch",
+ "coral"
+ );
+
+ private ChargerStateMonitor mChargerStateMonitor;
+
+ @Before
+ public void verifyCharging() {
+ if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) {
+ return;
+ }
+
+ mChargerStateMonitor = new ChargerStateMonitor();
+
+ assertTrue("Device must be connected to USB", mChargerStateMonitor.isCharging());
+ }
+
+ @Test
+ public void testSuspendInput() {
+ if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) {
+ return;
+ }
+
+ SystemUtil.runShellCommand("dumpsys battery suspend_input");
+
+ mChargerStateMonitor.waitForChargerState(/* isPluggedIn */false);
+ }
+
+ @After
+ public void reenableCharging() {
+ if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) {
+ return;
+ }
+
+ mChargerStateMonitor.reset();
+
+ SystemUtil.runShellCommand("dumpsys battery reset");
+
+ mChargerStateMonitor.waitForChargerState(/* isPluggedIn */true);
+ }
+
+ private static class ChargerStateMonitor {
+ private final Intent mBatteryMonitor;
+ private final ConditionVariable mReady = new ConditionVariable();
+ private boolean mExpectedChargingState;
+
+ ChargerStateMonitor() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ mBatteryMonitor = context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (isCharging(intent) == mExpectedChargingState) {
+ mReady.open();
+ }
+ }
+ }, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ }
+
+ public boolean isCharging() {
+ return isCharging(mBatteryMonitor);
+ }
+
+ private boolean isCharging(Intent batteryMonitor) {
+ return batteryMonitor.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
+ }
+
+ void waitForChargerState(boolean isPluggedIn) {
+ mExpectedChargingState = isPluggedIn;
+
+ boolean charging = isCharging();
+ if (charging == mExpectedChargingState) {
+ return;
+ }
+
+ boolean success = mReady.block(100000);
+ assertTrue("Timed out waiting for charging state to change", success);
+ }
+
+ void reset() {
+ mReady.close();
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
index 61d20df..3b27f18 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -18,6 +18,7 @@
import android.os.BatteryStats;
import android.os.Parcel;
+import android.os.SystemClock;
import androidx.test.filters.SmallTest;
@@ -36,9 +37,9 @@
timer.onTimeStarted(100, 100, 100);
// First update is absorbed.
- timer.update(10, 1);
+ timer.update(10, 1, SystemClock.elapsedRealtime() * 1000);
- timer.update(20, 2);
+ timer.update(20, 2, SystemClock.elapsedRealtime() * 1000);
assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED));
@@ -62,7 +63,7 @@
timeBase);
// First once is absorbed.
- timer.update(10, 1);
+ timer.update(10, 1, SystemClock.elapsedRealtime() * 1000);
timer.add(10, 1);
@@ -71,7 +72,7 @@
// This is less than we currently have, so we will end the sample. Time isn't running, so
// nothing should happen.
- timer.update(0, 0);
+ timer.update(0, 0, SystemClock.elapsedRealtime() * 1000);
assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED));
@@ -86,7 +87,7 @@
// This is less than we currently have, so we should end our sample and continue with the
// entire amount updated here.
- timer.update(50, 5);
+ timer.update(50, 5, SystemClock.elapsedRealtime() * 1000);
assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED));
assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
@@ -106,7 +107,7 @@
// This should be absorbed because it is our first update and we don't know what
// was being counted before.
- timer.update(10, 1);
+ timer.update(10, 1, SystemClock.elapsedRealtime() * 1000);
assertEquals(0, timer.getTotalTimeLocked(10, BatteryStats.STATS_SINCE_CHARGED));
assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
@@ -115,7 +116,7 @@
timer.onTimeStarted(100, 100, 100);
// This should be absorbed.
- timer.update(10, 1);
+ timer.update(10, 1, SystemClock.elapsedRealtime() * 1000);
assertEquals(0, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED));
assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
@@ -206,13 +207,13 @@
// Now, just like with a fresh timer, the first update should be absorbed to account for
// data being collected when we weren't recording.
- unparceledOnBatteryTimer.update(10, 10);
+ unparceledOnBatteryTimer.update(10, 10, SystemClock.elapsedRealtime() * 1000);
assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0,
BatteryStats.STATS_SINCE_CHARGED));
assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
- unparceledOffBatteryTimer.update(10, 10);
+ unparceledOffBatteryTimer.update(10, 10, SystemClock.elapsedRealtime() * 1000);
assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0,
BatteryStats.STATS_SINCE_CHARGED));
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
index df549c5..80e066c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
@@ -36,22 +36,22 @@
}
void populate() {
- mStartTime = 1010;
- mRunningSince = 2021;
+ mStartTimeMs = 1010;
+ mRunningSinceMs = 2021;
mRunning = true;
mStarts = 4042;
- mLaunchedTime = 5053;
- mLaunchedSince = 6064;
+ mLaunchedTimeMs = 5053;
+ mLaunchedSinceMs = 6064;
mLaunched = true;
mLaunches = 8085;
}
long getStartTime() {
- return mStartTime;
+ return mStartTimeMs;
}
long getRunningSince() {
- return mRunningSince;
+ return mRunningSinceMs;
}
void setRunning(boolean val) {
@@ -67,11 +67,11 @@
}
long getLaunchedTime() {
- return mLaunchedTime;
+ return mLaunchedTimeMs;
}
long getLaunchedSince() {
- return mLaunchedSince;
+ return mLaunchedSinceMs;
}
void setLaunched(boolean val) {
@@ -173,7 +173,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
@@ -202,7 +207,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
@@ -229,7 +239,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
TestServ serv = new TestServ(bsi);
@@ -259,7 +274,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
TestServ serv = new TestServ(bsi);
@@ -316,7 +336,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
TestServ serv = new TestServ(bsi);
@@ -345,7 +370,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
TestServ serv = new TestServ(bsi);
@@ -374,7 +404,12 @@
MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
@Override
public long getBatteryUptimeLocked() {
- return 777777L;
+ return 777777L * 1000; // microseconds
+ }
+
+ @Override
+ public long getBatteryUptimeLocked(long uptimeMs) {
+ return 777777L * 1000; // microseconds
}
};
TestServ serv = new TestServ(bsi);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
index e5441c0..f016e75a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
@@ -41,29 +41,29 @@
public void populate(long uptime, long realtime, boolean running, long pastUptime,
long uptimeStart, long pastRealtime, long realtimeStart,
long unpluggedUptime, long unpluggedRealtime) {
- mUptime = uptime;
- mRealtime = realtime;
+ mUptimeUs = uptime;
+ mRealtimeUs = realtime;
mRunning = running;
- mPastUptime = pastUptime;
- mUptimeStart = uptimeStart;
- mPastRealtime = pastRealtime;
- mRealtimeStart = realtimeStart;
- mUnpluggedUptime = unpluggedUptime;
- mUnpluggedRealtime = unpluggedRealtime;
+ mPastUptimeUs = pastUptime;
+ mUptimeStartUs = uptimeStart;
+ mPastRealtimeUs = pastRealtime;
+ mRealtimeStartUs = realtimeStart;
+ mUnpluggedUptimeUs = unpluggedUptime;
+ mUnpluggedRealtimeUs = unpluggedRealtime;
}
public void verify(long uptime, long realtime, boolean running, long pastUptime,
long uptimeStart, long pastRealtime, long realtimeStart,
long unpluggedUptime, long unpluggedRealtime) {
- Assert.assertEquals(uptime, mUptime);
- Assert.assertEquals(realtime, mRealtime);
+ Assert.assertEquals(uptime, mUptimeUs);
+ Assert.assertEquals(realtime, mRealtimeUs);
Assert.assertEquals(running, mRunning);
- Assert.assertEquals(pastUptime, mPastUptime);
- Assert.assertEquals(uptimeStart, mUptimeStart);
- Assert.assertEquals(pastRealtime, mPastRealtime);
- Assert.assertEquals(realtimeStart, mRealtimeStart);
- Assert.assertEquals(unpluggedUptime, mUnpluggedUptime);
- Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtime);
+ Assert.assertEquals(pastUptime, mPastUptimeUs);
+ Assert.assertEquals(uptimeStart, mUptimeStartUs);
+ Assert.assertEquals(pastRealtime, mPastRealtimeUs);
+ Assert.assertEquals(realtimeStart, mRealtimeStartUs);
+ Assert.assertEquals(unpluggedUptime, mUnpluggedUptimeUs);
+ Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtimeUs);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
index 40e3a5f..11a01b3 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
@@ -49,7 +49,8 @@
super(clocks, type, timeBase);
}
- protected long computeRunTimeLocked(long curBatteryRealtime) {
+ @Override
+ protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
lastComputeRunTimeRealtime = curBatteryRealtime;
return nextComputeRunTime;
}
@@ -67,19 +68,19 @@
}
public long getTotalTime() {
- return mTotalTime;
+ return mTotalTimeUs;
}
public void setTotalTime(long val) {
- mTotalTime = val;
+ mTotalTimeUs = val;
}
public long getTimeBeforeMark() {
- return mTimeBeforeMark;
+ return mTimeBeforeMarkUs;
}
public void setTimeBeforeMark(long val) {
- mTimeBeforeMark = val;
+ mTimeBeforeMarkUs = val;
}
}
diff --git a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
index 359bd5e..f1cd89b 100644
--- a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
@@ -16,8 +16,16 @@
package com.android.internal.util;
+import static com.android.internal.util.HexDump.hexStringToByteArray;
+import static com.android.internal.util.HexDump.toHexString;
+
import junit.framework.TestCase;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Random;
+
public final class HexDumpTest extends TestCase {
public void testBytesToHexString() {
assertEquals("abcdef", HexDump.toHexString(
@@ -25,7 +33,143 @@
assertEquals("ABCDEF", HexDump.toHexString(
new byte[] { (byte) 0xab, (byte) 0xcd, (byte) 0xef }, true));
}
- public void testNullArray() {
- assertEquals("(null)", HexDump.toHexString(null));
+
+ public void testNullByteArray() {
+ assertThrows(
+ NullPointerException.class,
+ () -> HexDump.toHexString(null));
}
+
+ public void testBytesToHexString_allByteValues() {
+ byte[] bytes = new byte[256];
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[i] = (byte) (i % 256);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (char firstChar : "0123456789ABCDEF".toCharArray()) {
+ for (char secondChar : "0123456789ABCDEF".toCharArray()) {
+ sb.append(firstChar).append(secondChar);
+ }
+ }
+ String expected = sb.toString();
+
+ assertEquals(expected, HexDump.toHexString(bytes));
+ }
+
+ public void testRoundTrip_fromBytes() {
+ Random deterministicRandom = new Random(31337); // arbitrary but deterministic
+ for (int length = 0; length < 100; length++) {
+ byte[] bytes = new byte[length];
+ deterministicRandom.nextBytes(bytes);
+ byte[] reconstruction = hexStringToByteArray(toHexString(bytes));
+
+ assertBytesEqual(bytes, reconstruction);
+ }
+ }
+
+ public void testRoundTrip_fromString() {
+ String hexString = "0123456789ABCDEF72f9a3438934c378d34f32a8b932";
+ for (int length = 0; length < hexString.length(); length += 2) {
+ String original = hexString.substring(0, length);
+ String reconstruction = toHexString(hexStringToByteArray(original));
+ assertEquals(original.toUpperCase(), reconstruction);
+ }
+ }
+
+ public void testToHexString_offsetLength() {
+ byte[] bytes = new byte[32];
+ for (int i = 0; i < 16; i++) {
+ bytes[i] = (byte) i;
+ bytes[16 + i] = (byte) (16 * i);
+ }
+ String expected = "000102030405060708090A0B0C0D0E0F00102030405060708090A0B0C0D0E0F0";
+ for (int offset = 0; offset < bytes.length; offset++) {
+ for (int len = 0; len < (bytes.length - offset); len++) {
+
+ byte[] subBytes = new byte[len];
+ System.arraycopy(bytes, offset, subBytes, 0, len);
+
+ String actual = toHexString(bytes, offset, len);
+ assertEquals(expected.substring(2 * offset, 2 * offset + 2 * len), actual);
+ assertEquals(toHexString(subBytes), actual);
+ }
+ }
+ }
+
+ public void testToHexString_case() {
+ byte[] bytes = new byte[32];
+ for (int i = 0; i < 16; i++) {
+ bytes[i] = (byte) i;
+ bytes[16 + i] = (byte) (16 * i);
+ }
+
+ String expected = "000102030405060708090A0B0C0D0E0F00102030405060708090A0B0C0D0E0F0";
+
+ assertEquals(expected.toUpperCase(), toHexString(bytes, true));
+ assertEquals(expected.toLowerCase(), toHexString(bytes, false));
+
+ // default is uppercase
+ assertEquals(expected.toUpperCase(), toHexString(bytes));
+ }
+
+ public void testHexStringToByteArray_empty() {
+ assertBytesEqual(new byte[0], HexDump.hexStringToByteArray(""));
+ }
+
+ public void testHexStringToByteArray_null() {
+ assertThrows(
+ NullPointerException.class,
+ () -> HexDump.hexStringToByteArray((String) null));
+ }
+
+ public void testHexStringToByteArray_invalidCharacters() {
+ // IllegalArgumentException would probably have been better than RuntimeException, but it
+ // might be too late to change now.
+ assertThrows(
+ RuntimeException.class,
+ () -> HexDump.hexStringToByteArray("GG"));
+ assertThrows(
+ RuntimeException.class,
+ () -> HexDump.hexStringToByteArray("\0\0"));
+ assertThrows(
+ RuntimeException.class,
+ () -> HexDump.hexStringToByteArray("abcdefgh"));
+ }
+
+ public void testHexStringToByteArray_oddLength() {
+ // IllegalArgumentException would probably have been better than
+ // StringIndexOutOfBoundsException, but it might be too late to change now.
+ assertThrows(
+ StringIndexOutOfBoundsException.class,
+ () -> HexDump.hexStringToByteArray("A"));
+ assertThrows(
+ StringIndexOutOfBoundsException.class,
+ () -> HexDump.hexStringToByteArray("123"));
+ assertThrows(
+ StringIndexOutOfBoundsException.class,
+ () -> HexDump.hexStringToByteArray("ABCDE"));
+ }
+
+ private static void assertBytesEqual(byte[] expected, byte[] actual) {
+ if (!Arrays.equals(expected, actual)) {
+ fail("Expected " + Arrays.toString(expected) + ", got " + Arrays.toString(actual));
+ }
+ }
+
+ private static void assertThrows(Class<? extends RuntimeException> clazz, Runnable runnable) {
+ try {
+ runnable.run();
+ fail();
+ } catch (RuntimeException expected) {
+ assertEquals(toStrackTrace(expected), clazz, expected.getClass());
+ }
+ }
+
+ private static String toStrackTrace(Throwable throwable) {
+ StringWriter stringWriter = new StringWriter();
+ throwable.printStackTrace(new PrintWriter(stringWriter));
+ return stringWriter.toString();
+ }
+
}
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 7292e07..59aa45e 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -40,6 +40,7 @@
<permission name="android.permission.REAL_GET_TASKS"/>
<permission name="android.permission.READ_LOGS"/>
<permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"/>
<!-- use for CarServiceTest -->
<permission name="android.permission.SET_ACTIVITY_WATCHER"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index a2a2216..e693198 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1393,6 +1393,12 @@
"group": "WM_SHOW_SURFACE_ALLOC",
"at": "com\/android\/server\/wm\/BlackFrame.java"
},
+ "155482615": {
+ "message": "Focus requested for window=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/InputMonitor.java"
+ },
"174572959": {
"message": "DisplayArea info changed name=%s",
"level": "VERBOSE",
@@ -2635,6 +2641,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
},
+ "2081291430": {
+ "message": "Focus not requested for window=%s because it has no surface",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/InputMonitor.java"
+ },
"2083556954": {
"message": "Set mOrientationChanging of %s",
"level": "VERBOSE",
diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp
index 4f4364f..7fbbb61 100644
--- a/libs/WindowManager/Jetpack/Android.bp
+++ b/libs/WindowManager/Jetpack/Android.bp
@@ -24,14 +24,14 @@
static_libs: ["window-sidecar"],
installable: true,
sdk_version: "core_platform",
- vendor: true,
+ system_ext_specific: true,
libs: ["framework", "androidx.annotation_annotation",],
required: ["androidx.window.sidecar.xml",],
}
prebuilt_etc {
name: "androidx.window.sidecar.xml",
- vendor: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "androidx.window.sidecar.xml",
filename_from_src: true,
diff --git a/libs/WindowManager/Jetpack/androidx.window.sidecar.xml b/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
index f88a5f4..359e69f 100644
--- a/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
+++ b/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
@@ -17,5 +17,5 @@
<permissions>
<library
name="androidx.window.sidecar"
- file="/vendor/framework/androidx.window.sidecar.jar"/>
+ file="/system_ext/framework/androidx.window.sidecar.jar"/>
</permissions>
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 16b87c4..1591b06 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -105,6 +105,7 @@
static_libs: [
"protolog-lib",
"WindowManager-Shell-proto",
+ "androidx.appcompat_appcompat",
],
manifest: "AndroidManifest.xml",
}
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png b/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png
rename to libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/xml/one_handed_tutorial.xml b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
similarity index 100%
rename from packages/SystemUI/res/xml/one_handed_tutorial.xml
rename to libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 7242793..a13e98c 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,6 +1,12 @@
{
"version": "1.0.0",
"messages": {
+ "-1501874464": {
+ "message": "Fullscreen Task Appeared: #%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
+ },
"-1340279385": {
"message": "Remove listener=%s",
"level": "VERBOSE",
@@ -31,6 +37,12 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
+ "564235578": {
+ "message": "Fullscreen Task Vanished: #%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
+ },
"980952660": {
"message": "Task root back pressed taskId=%d",
"level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 39efd07..63b0f6f 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -29,4 +29,7 @@
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
+
+ <!-- Allow one handed to enable round corner -->
+ <bool name="config_one_handed_enable_round_corner">true</bool>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index ce69028..7fb641a 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -62,4 +62,8 @@
<dimen name="docked_divider_handle_width">16dp</dimen>
<dimen name="docked_divider_handle_height">2dp</dimen>
+
+ <!-- One-Handed Mode -->
+ <!-- Threshold for dragging distance to enable one-handed mode -->
+ <dimen name="gestures_onehanded_drag_threshold">20dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index cad9247..b6668fb 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -88,4 +88,9 @@
<string name="accessibility_action_divider_top_30">Top 30%</string>
<!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
<string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
+
+ <!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
+ <string name="one_handed_tutorial_title">Using one-handed mode</string>
+ <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
+ <string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
new file mode 100644
index 0000000..d0051db
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.wm.shell;
+
+import android.app.ActivityManager;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = "FullscreenTaskOrg";
+
+ private final TransactionPool mTransactionPool;
+
+ private final ArraySet<Integer> mTasks = new ArraySet<>();
+
+ FullscreenTaskListener(TransactionPool transactionPool) {
+ mTransactionPool = transactionPool;
+ }
+
+ @Override
+ public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+ synchronized (mTasks) {
+ if (mTasks.contains(taskInfo.taskId)) {
+ throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
+ }
+ mTasks.add(taskInfo.taskId);
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
+ taskInfo.taskId);
+ t.show(leash);
+ t.apply();
+ }
+ }
+
+ @Override
+ public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
+ synchronized (mTasks) {
+ if (!mTasks.remove(taskInfo.taskId)) {
+ Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
+ taskInfo.taskId);
+ }
+ }
+
+ @Override
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index f9ba695c..2d82fb1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,6 +16,8 @@
package com.android.wm.shell;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.util.Log;
import android.util.Pair;
@@ -26,6 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList;
@@ -56,13 +59,16 @@
// require us to report to both old and new listeners)
private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>();
- public ShellTaskOrganizer() {
+ public ShellTaskOrganizer(TransactionPool transactionPool) {
super();
+ addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
}
@VisibleForTesting
- ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController) {
+ ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
+ TransactionPool transactionPool) {
super(taskOrganizerController);
+ addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
}
/**
@@ -125,6 +131,7 @@
Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
int winMode = getWindowingMode(taskInfo);
int prevWinMode = getWindowingMode(data.first);
+ mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
if (prevWinMode != -1 && prevWinMode != winMode) {
// TODO: We currently send vanished/appeared as the task moves between win modes, but
// we should consider adding a different mode-changed callback
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 8abe9ee..b4620e27 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
-import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
@@ -32,7 +31,6 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
-import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IScrollCaptureController;
import android.view.IWindow;
@@ -47,6 +45,7 @@
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
+import android.window.ClientWindowFrames;
import com.android.internal.os.IResultReceiver;
@@ -274,22 +273,20 @@
@Override
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
- long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
- Rect outVisibleInsets, Rect outStableInsets,
- DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
+ long frameNumber, ClientWindowFrames outFrames,
+ MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
SurfaceControl outBLASTSurfaceControl) {
int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
- viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
- outContentInsets, outVisibleInsets, outStableInsets,
- cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
+ viewVisibility, flags, frameNumber, outFrames,
+ mergedConfiguration, outSurfaceControl, outInsetsState,
outActiveControls, outSurfaceSize, outBLASTSurfaceControl);
if (res != 0) {
return res;
}
DisplayLayout dl = mDisplayController.getDisplayLayout(mDisplayId);
- outStableInsets.set(dl.stableInsets());
+ outFrames.stableInsets.set(dl.stableInsets());
return 0;
}
@@ -314,10 +311,9 @@
ContainerWindow() {}
@Override
- public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, Rect stableInsets,
- boolean reportDraw, MergedConfiguration newMergedConfiguration, Rect backDropFrame,
- boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {}
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration newMergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {}
@Override
public void locationInParentDisplayChanged(Point offset) {}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index b7c6262..9c78fc5 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import androidx.annotation.NonNull;
-import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationCallback.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationCallback.java
index 264ace7..6749f7e 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationCallback.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.view.SurfaceControl;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
index 9be1b5a..9639096 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.animation.Animator;
import android.animation.ValueAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 90adf83..c84b478 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -35,9 +35,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;
@@ -390,7 +390,7 @@
}
}
- @androidx.annotation.VisibleForTesting
+ @VisibleForTesting
private void setEnabledGesturalOverlay(boolean enabled) {
try {
mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index ec40bad..9954618 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
-import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
+import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
+import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
import android.content.Context;
import android.graphics.Point;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedEvents.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEvents.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedEvents.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEvents.java
index 327ed67..79ddd2b 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedEvents.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEvents.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 4a493ba..3b1e6cb 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -38,7 +38,7 @@
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
@@ -210,7 +210,7 @@
displaySize.y);
mInputMonitor = InputManager.getInstance().monitorGestureInput(
"onehanded-gesture-offset", DEFAULT_DISPLAY);
- mInputEventReceiver = new SysUiInputEventReceiver(
+ mInputEventReceiver = new EventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper());
}
}
@@ -227,8 +227,8 @@
mRotation = toRotation;
}
- private class SysUiInputEventReceiver extends InputEventReceiver {
- SysUiInputEventReceiver(InputChannel channel, Looper looper) {
+ private class EventReceiver extends InputEventReceiver {
+ EventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 0598f32..4d66f29 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.annotation.IntDef;
import android.content.ContentResolver;
@@ -22,8 +22,6 @@
import android.net.Uri;
import android.provider.Settings;
-import com.android.systemui.dagger.SysUISingleton;
-
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -31,7 +29,6 @@
/**
* APIs for querying or updating one handed settings .
*/
-@SysUISingleton
public final class OneHandedSettingsUtil {
private static final String TAG = "OneHandedSettingsUtil";
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSurfaceTransactionHelper.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSurfaceTransactionHelper.java
index bc4a9b4..e7010db 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSurfaceTransactionHelper.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.view.SurfaceControl;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
/**
* Abstracts the common operations on {@link SurfaceControl.Transaction} for OneHanded transition.
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedThread.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedThread.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedThread.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedThread.java
index b7b814a..24d33ed 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedThread.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedThread.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java
index 21329ea..9c97cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import android.os.Handler;
import android.os.Looper;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
index 3d28a42..721382d 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -127,7 +127,7 @@
if (mIsEnabled) {
mInputMonitor = InputManager.getInstance().monitorGestureInput(
"onehanded-touch", DEFAULT_DISPLAY);
- mInputEventReceiver = new SysUiInputEventReceiver(
+ mInputEventReceiver = new EventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper());
}
}
@@ -150,8 +150,8 @@
pw.println(mLastUpdatedBounds);
}
- private class SysUiInputEventReceiver extends InputEventReceiver {
- SysUiInputEventReceiver(InputChannel channel, Looper looper) {
+ private class EventReceiver extends InputEventReceiver {
+ EventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTransitionCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTransitionCallback.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTransitionCallback.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTransitionCallback.java
index 75eb0eb..3af7c4b 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTransitionCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTransitionCallback.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.graphics.Rect;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index beccf3d..b15b515 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import android.content.ContentResolver;
import android.content.Context;
@@ -33,7 +33,7 @@
import androidx.annotation.NonNull;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
import java.io.PrintWriter;
@@ -79,7 +79,7 @@
mTargetViewContainer.setClipChildren(false);
mTutorialAreaHeight = Math.round(mDisplaySize.y
* (SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f));
- mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null);
+ mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer.addView(mTutorialView);
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
index 015707e..25827cd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
@@ -194,7 +194,7 @@
*/
boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) {
// Set launchtile first so that any stack created after
- // getAllStackInfos and before reparent (even if unlikely) are placed
+ // getAllRootTaskInfos and before reparent (even if unlikely) are placed
// correctly.
mTaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
List<ActivityManager.RunningTaskInfo> rootTasks =
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index 5879022..d7afa0e 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -18,7 +18,7 @@
name: "WMShellFlickerTests",
srcs: ["src/**/*.java", "src/**/*.kt"],
manifest: "AndroidManifest.xml",
- test_config: "AndroidTest.xml",
+ test_config: "AndroidTestPhysicalDevices.xml",
platform_apis: true,
certificate: "platform",
test_suites: ["device-tests"],
@@ -32,3 +32,21 @@
"launcher-aosp-tapl"
],
}
+
+android_test {
+ name: "WMShellFlickerTestsVirtual",
+ srcs: ["src/**/*.java", "src/**/*.kt"],
+ manifest: "AndroidManifest.xml",
+ test_config: "AndroidTestVirtualDevices.xml",
+ platform_apis: true,
+ certificate: "platform",
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "flickerlib",
+ "truth-prebuilt",
+ "app-helpers-core",
+ "launcher-helper-lib",
+ "launcher-aosp-tapl"
+ ],
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestPhysicalDevices.xml
similarity index 95%
copy from libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
copy to libs/WindowManager/Shell/tests/flicker/AndroidTestPhysicalDevices.xml
index 526fc50..9dd9f42 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestPhysicalDevices.xml
@@ -27,6 +27,7 @@
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.wm.shell.flicker"/>
+ <option name="include-annotation" value="androidx.test.filters.RequiresDevice" />
<option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
<option name="shell-timeout" value="6600s" />
<option name="test-timeout" value="6000s" />
@@ -37,4 +38,4 @@
<option name="collect-on-run-ended-only" value="true" />
<option name="clean-up" value="true" />
</metrics_collector>
-</configuration>
+</configuration>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml
similarity index 95%
rename from libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
rename to libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml
index 526fc50..afb1166 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml
@@ -27,6 +27,7 @@
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.wm.shell.flicker"/>
+ <option name="exclude-annotation" value="androidx.test.filters.RequiresDevice" />
<option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
<option name="shell-timeout" value="6600s" />
<option name="test-timeout" value="6000s" />
@@ -37,4 +38,4 @@
<option name="collect-on-run-ended-only" value="true" />
<option name="clean-up" value="true" />
</metrics_collector>
-</configuration>
+</configuration>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
index 308a36e..47a62ce 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
@@ -18,7 +18,7 @@
import android.app.Instrumentation
import android.support.test.launcherhelper.ILauncherStrategy
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
abstract class FlickerAppHelper(
instr: Instrumentation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 4b04449..c3c576d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -18,7 +18,7 @@
import android.view.Surface
import androidx.test.filters.FlakyTest
-import androidx.test.filters.LargeTest
+import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.closePipWindow
import com.android.server.wm.flicker.helpers.expandPipWindow
@@ -41,7 +41,7 @@
* Test Pip launch.
* To run this test: `atest FlickerTests:PipToAppTest`
*/
-@LargeTest
+@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 692e2fa..937b00b 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -25,6 +25,7 @@
"androidx.test.ext.junit",
"mockito-target-extended-minus-junit4",
"truth-prebuilt",
+ "testables",
],
libs: [
"android.test.mock",
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 497b6b7..7b499d4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo;
@@ -32,6 +33,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.wm.shell.common.TransactionPool;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,6 +54,7 @@
private ITaskOrganizerController mTaskOrganizerController;
ShellTaskOrganizer mOrganizer;
+ private final TransactionPool mTransactionPool = mock(TransactionPool.class);
private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener {
final ArrayList<RunningTaskInfo> appeared = new ArrayList<>();
@@ -81,7 +85,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController);
+ mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController, mTransactionPool);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
index 7fabf82..a8a3a9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static org.junit.Assert.assertNotNull;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
similarity index 87%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index e42cf52..1ce8b54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static com.google.common.truth.Truth.assertThat;
@@ -112,11 +112,22 @@
}
@Test
- public void testRegisterTransitionCallback() {
- verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerTransitionCallback(any());
+ public void testRegisterTransitionCallbackAfterInit() {
+ verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTouchHandler);
+ verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockGestureHandler);
+ verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler);
}
@Test
+ public void testRegisterTransitionCallback() {
+ OneHandedTransitionCallback callback = new OneHandedTransitionCallback() {};
+ mOneHandedController.registerTransitionCallback(callback);
+
+ verify(mMockDisplayAreaOrganizer).registerTransitionCallback(callback);
+ }
+
+
+ @Test
public void testStopOneHanded_shouldRemoveTimer() {
mOneHandedController.stopOneHanded();
@@ -139,7 +150,7 @@
verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
}
- @Ignore("b/161980408, fix it after migration finished")
+ @Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateTapAppToExit() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -148,7 +159,7 @@
verify(mOneHandedController).setTaskChangeToExit(true);
}
- @Ignore("b/161980408, fix it after migration finished")
+ @Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -157,7 +168,7 @@
verify(mOneHandedController).setOneHandedEnabled(true);
}
- @Ignore("b/161980408, fix it after migration finished")
+ @Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateTimeout() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -168,7 +179,7 @@
OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
}
- @Ignore("b/161980408, fix it after migration finished")
+ @Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateSwipeToNotification() {
Settings.Secure.putInt(mContext.getContentResolver(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
similarity index 99%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index a989cd1f..5ff94b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedEventsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedEventsTest.java
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedEventsTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedEventsTest.java
index 36c1174..492c34e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedEventsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedEventsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static org.junit.Assert.assertEquals;
@@ -22,7 +22,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +33,7 @@
@RunWith(Parameterized.class)
@SmallTest
-public class OneHandedEventsTest extends SysuiTestCase {
+public class OneHandedEventsTest extends OneHandedTestCase {
private UiEventLoggerFake mUiEventLogger;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
new file mode 100644
index 0000000..fb417c8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 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.wm.shell.onehanded;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.common.DisplayController;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class OneHandedGestureHandlerTest extends OneHandedTestCase {
+ OneHandedTutorialHandler mTutorialHandler;
+ OneHandedGestureHandler mGestureHandler;
+ @Mock
+ DisplayController mMockDisplayController;
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTutorialHandler = new OneHandedTutorialHandler(mContext);
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
+ }
+
+ @Test
+ public void testSetGestureEventListener() {
+ OneHandedGestureHandler.OneHandedGestureEventCallback callback =
+ new OneHandedGestureHandler.OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {}
+
+ @Override
+ public void onStop() {}
+ };
+
+ mGestureHandler.setGestureEventListener(callback);
+ assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
+ }
+
+ @Ignore("b/167943723, refactor it and fix it")
+ @Test
+ public void testReceiveNewConfig_whenThreeButtonModeEnabled() {
+ mGestureHandler.onOneHandedEnabled(true);
+ mGestureHandler.onThreeButtonModeEnabled(true);
+
+ assertThat(mGestureHandler.mInputMonitor).isNotNull();
+ assertThat(mGestureHandler.mInputEventReceiver).isNotNull();
+ }
+
+ @Test
+ public void testOneHandedDisabled_shouldDisposeInputChannel() {
+ mGestureHandler.onOneHandedEnabled(false);
+
+ assertThat(mGestureHandler.mInputMonitor).isNull();
+ assertThat(mGestureHandler.mInputEventReceiver).isNull();
+ }
+
+ @Test
+ public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
+ mGestureHandler.onOneHandedEnabled(true);
+ mGestureHandler.onThreeButtonModeEnabled(false);
+
+ assertThat(mGestureHandler.mInputMonitor).isNull();
+ assertThat(mGestureHandler.mInputEventReceiver).isNull();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
similarity index 83%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
index 990eb63..7c11138 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
import static com.google.common.truth.Truth.assertThat;
@@ -59,24 +59,24 @@
@Test
public void testRegisterSecureKeyObserver() {
final Uri result = OneHandedSettingsUtil.registerSettingsKeyObserver(
- Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
+ Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
assertThat(result).isNotNull();
OneHandedSettingsUtil.registerSettingsKeyObserver(
- Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
+ Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
}
@Test
public void testUnregisterSecureKeyObserver() {
OneHandedSettingsUtil.registerSettingsKeyObserver(
- Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
+ Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
OneHandedSettingsUtil.unregisterSettingsKeyObserver(mContentResolver, mContentObserver);
assertThat(mOnChanged).isFalse();
Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 0);
+ Settings.Secure.TAPS_APP_TO_EXIT, 0);
assertThat(mOnChanged).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
similarity index 73%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
index f111c48..c7ae2a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java
@@ -14,17 +14,21 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
-import static com.android.systemui.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static org.junit.Assume.assumeTrue;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
import android.os.SystemProperties;
import android.provider.Settings;
-import com.android.systemui.SysuiTestCase;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -32,14 +36,26 @@
/**
* Base class that does One Handed specific setup.
*/
-public abstract class OneHandedTestCase extends SysuiTestCase {
+public abstract class OneHandedTestCase {
static boolean sOrigEnabled;
static boolean sOrigTapsAppToExitEnabled;
static int sOrigTimeout;
static boolean sOrigSwipeToNotification;
+ protected Context mContext;
+
@Before
public void setupSettings() {
+ final Context testContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final DisplayManager dm = testContext.getSystemService(DisplayManager.class);
+ mContext = testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
+
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity();
+
sOrigEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
getContext().getContentResolver());
sOrigTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
@@ -74,6 +90,15 @@
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
sOrigSwipeToNotification ? 1 : 0);
+
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ protected Context getContext() {
+ return mContext;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTimeoutHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
similarity index 90%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTimeoutHandlerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
index 7d63131..e2b70c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTimeoutHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
-import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
-import static com.android.systemui.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
+import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
+import static com.android.wm.shell.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG;
import static com.google.common.truth.Truth.assertThat;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java
new file mode 100644
index 0000000..c69e385
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.wm.shell.onehanded;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class OneHandedTouchHandlerTest extends OneHandedTestCase {
+ OneHandedTouchHandler mTouchHandler;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mTouchHandler = new OneHandedTouchHandler();
+ }
+
+ @Test
+ public void testRegisterTouchEventListener() {
+ OneHandedTouchHandler.OneHandedTouchEventCallback callback = () -> {
+ };
+ mTouchHandler.registerTouchEventListener(callback);
+
+ assertThat(mTouchHandler.mTouchEventCallback).isEqualTo(callback);
+ }
+
+ @Test
+ public void testOneHandedDisabled_shouldDisposeInputChannel() {
+ mTouchHandler.onOneHandedEnabled(false);
+
+ assertThat(mTouchHandler.mInputMonitor).isNull();
+ assertThat(mTouchHandler.mInputEventReceiver).isNull();
+ }
+
+ @Ignore("b/167943723, refactor it and fix it")
+ @Test
+ public void testOneHandedEnabled_monitorInputChannel() {
+ mTouchHandler.onOneHandedEnabled(true);
+
+ assertThat(mTouchHandler.mInputMonitor).isNotNull();
+ assertThat(mTouchHandler.mInputEventReceiver).isNotNull();
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
similarity index 90%
rename from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index 8ea5524..4a133d39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded;
+package com.android.wm.shell.onehanded;
import static org.mockito.Mockito.verify;
@@ -29,13 +29,13 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
+ @Mock
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
@@ -48,8 +48,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mTouchHandler = new OneHandedTouchHandler();
- mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
+ mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index a23191f..523a072 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -15,8 +15,10 @@
*/
package android.media;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.StringDef;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.graphics.Bitmap;
@@ -738,15 +740,16 @@
/**
* Create a Builder using a {@link MediaMetadata} instance to set
- * initial values, but replace bitmaps with a scaled down copy if they
- * are larger than maxBitmapSize.
+ * initial values, but replace bitmaps with a scaled down copy if their width (or height)
+ * is larger than maxBitmapSize.
*
* @param source The original metadata to copy.
* @param maxBitmapSize The maximum height/width for bitmaps contained
* in the metadata.
* @hide
*/
- public Builder(MediaMetadata source, int maxBitmapSize) {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public Builder(@NonNull MediaMetadata source, @IntRange(from = 1) int maxBitmapSize) {
this(source);
for (String key : mBundle.keySet()) {
Object value = mBundle.get(key);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 36ae3ec..851c1ec 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -19,6 +19,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
@@ -2092,6 +2094,8 @@
mOnInfoListener = null;
mOnVideoSizeChangedListener = null;
mOnTimedTextListener = null;
+ mOnImsRxNoticeListener = null;
+ mOnImsRxNoticeHandler = null;
synchronized (mTimeProviderLock) {
if (mTimeProvider != null) {
mTimeProvider.close();
@@ -3299,6 +3303,7 @@
private static final int MEDIA_META_DATA = 202;
private static final int MEDIA_DRM_INFO = 210;
private static final int MEDIA_TIME_DISCONTINUITY = 211;
+ private static final int MEDIA_IMS_RX_NOTICE = 300;
private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
private TimeProvider mTimeProvider;
@@ -3608,6 +3613,35 @@
}
return;
+ case MEDIA_IMS_RX_NOTICE:
+ final OnImsRxNoticeListener imsRxNoticeListener;
+ final Handler imsRxNoticeHandler;
+ imsRxNoticeListener = mOnImsRxNoticeListener;
+ imsRxNoticeHandler = mOnImsRxNoticeHandler;
+ if (imsRxNoticeListener == null) {
+ return;
+ }
+ if (msg.obj instanceof Parcel) {
+ Parcel parcel = (Parcel) msg.obj;
+ byte[] event;
+ try {
+ event = parcel.marshall();
+ } finally {
+ parcel.recycle();
+ }
+ if (imsRxNoticeHandler == null) {
+ imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
+ } else {
+ imsRxNoticeHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
+ }
+ });
+ }
+ }
+ return;
+
default:
Log.e(TAG, "Unknown message type " + msg.what);
return;
@@ -4048,6 +4082,146 @@
}
/**
+ * Interface definition of a callback to be invoked when
+ * IMS Rx connection has a notice.
+ *
+ * @see MediaPlayer.setOnImsRxNoticeListener
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface OnImsRxNoticeListener
+ {
+ /**
+ * Called to indicate an IMS event noticed from native media frameworks.
+ * <p></p>
+ * Basic format. All TYPE and ARG are 4 bytes unsigned integer in native byte order.
+ * <pre>{@code
+ * 0 4 8 12
+ * +----------------+---------------+----------------+----------------+
+ * | TYPE | ARG1 | ARG2 | ARG3 |
+ * +----------------+---------------+----------------+----------------+
+ * | ARG4 | ARG5 | ...
+ * +----------------+---------------+-------------
+ * 16 20 24
+ *
+ *
+ * TYPE 100 - A notice of the first rtp packet received. No ARGs.
+ * 0
+ * +----------------+
+ * | 100 |
+ * +----------------+
+ *
+ *
+ * TYPE 101 - A notice of the first rtcp packet received. No ARGs.
+ * 0
+ * +----------------+
+ * | 101 |
+ * +----------------+
+ *
+ *
+ * TYPE 102 - A periodic report of a RTP statistics.
+ * TYPE 103 - An emergency report when serious packet loss has been detected
+ * in between TYPE 102 events.
+ * 0 4 8 12
+ * +----------------+---------------+----------------+----------------+
+ * | 102 or 103 | FB type=0 | Bitrate | Top #.Seq |
+ * +----------------+---------------+----------------+----------------+
+ * | Base #.Seq |Prev Expt #.Pkt| Recv #.Pkt |Prev Recv #.Pkt |
+ * +----------------+---------------+----------------+----------------+
+ * Feedback (FB) type
+ * - always 0.
+ * Bitrate
+ * - amount of data received in this period.
+ * Top number of sequence
+ * - highest RTP sequence number received in this period.
+ * - monotonically increasing value.
+ * Base number of sequence
+ * - the first RTP sequence number of the media stream.
+ * Previous Expected number of Packets
+ * - expected count of packets received in the previous report.
+ * Received number of packet
+ * - actual count of packets received in this report.
+ * Previous Received number of packet
+ * - actual count of packets received in the previous report.
+ *
+ *
+ * TYPE 205 - Transport layer Feedback message. (RFC-5104 Sec.4.2)
+ * 0 4 8 12
+ * +----------------+---------------+----------------+----------------+
+ * | 205 | SSRC | FB type(1 or 3)| value |
+ * +----------------+---------------+----------------+----------------+
+ * SSRC
+ * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
+ * Feedback (FB) type: determines the type of the event.
+ * - if 1, we received a NACK request from the remote side.
+ * - if 3, we received a TMMBR (Temporary Maximum Media Stream Bit Rate Request) from
+ * the remote side.
+ * Value: the FCI (Feedback Control Information) depending on the value of FB type
+ * - if FB type is 1, the Generic NACK as specified in RFC-4585 Sec.6.2.1
+ * - if FB type is 3, the TMMBR as specified in RFC-5104 Sec.4.2.1.1
+ *
+ *
+ * TYPE 206 - Payload-specific Feedback message. (RFC-5104 Sec.4.3)
+ * 0 4 8
+ * +----------------+---------------+----------------+
+ * | 206 | SSRC | FB type(1 or 4)|
+ * +----------------+---------------+----------------+
+ * SSRC
+ * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
+ * Feedback (FB) type: determines the type of the event.
+ * - if 1, we received a PLI request from the remote side.
+ * - if 4, we received a FIR request from the remote side.
+ *
+ *
+ * TYPE 300 - CVO (RTP Extension) message.
+ * 0 4
+ * +----------------+---------------+
+ * | 101 | value |
+ * +----------------+---------------+
+ * value
+ * - clockwise rotation degrees of a received video (6.2.3 of 3GPP R12 TS 26.114).
+ * - can be 0 (degree 0), 1 (degree 90), 2 (degree 180) or 3 (degree 270).
+ *
+ *
+ * TYPE 400 - Socket failed during receive. No ARGs.
+ * 0
+ * +----------------+
+ * | 400 |
+ * +----------------+
+ * }</pre>
+ *
+ * @param mp the {@code MediaPlayer} associated with this callback.
+ * @param event an IMS media event serialized as byte[] array.
+ */
+ void onImsRxNotice(@NonNull MediaPlayer mp, @NonNull byte[] event);
+ }
+
+ /**
+ * Register a callback to be invoked when IMS Rx connection has a notice.
+ * The callback required if mediaplayer configured for RTPSource by
+ * MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h
+ *
+ * @see MediaPlayer.OnImsRxNoticeListener
+ *
+ * @param listener the callback that will be run
+ * @param handler Specifies Handler object for the thread on which to execute
+ * the callback. If null, the handler on the main looper will be used.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission("android.permission.BIND_IMS_SERVICE")
+ public void setOnImsRxNoticeListener(
+ @Nullable OnImsRxNoticeListener listener, @Nullable Handler handler) {
+ mOnImsRxNoticeListener = listener;
+ mOnImsRxNoticeHandler = handler;
+ }
+
+ private OnImsRxNoticeListener mOnImsRxNoticeListener;
+ private Handler mOnImsRxNoticeHandler;
+
+ /**
* Register a callback to be invoked when a selected track has timed metadata available.
* <p>
* Currently only HTTP live streaming data URI's embedded with timed ID3 tags generates
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 549e793..624607b 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -828,9 +828,10 @@
}
/**
- * Gets the UID of this token.
+ * Gets the UID of the application that created the media session.
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public int getUid() {
return mUid;
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index bb40e24..26a0ad9 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -6532,6 +6532,7 @@
method public android.graphics.Bitmap takeScreenshot();
method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
+ field public static final int FLAG_DONT_USE_ACCESSIBILITY = 2; // 0x2
field public static final int ROTATION_FREEZE_0 = 0; // 0x0
field public static final int ROTATION_FREEZE_180 = 2; // 0x2
field public static final int ROTATION_FREEZE_270 = 3; // 0x3
@@ -50983,6 +50984,7 @@
method public final boolean isFunctionPressed();
method public static final boolean isGamepadButton(int);
method public final boolean isLongPress();
+ method public static final boolean isMediaSessionKey(int);
method public final boolean isMetaPressed();
method public static boolean isModifierKey(int);
method public final boolean isNumLockOn();
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index aec4ff53..f7f42d0 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -41,6 +41,10 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
+ public static final class MediaMetadata.Builder {
+ ctor public MediaMetadata.Builder(@NonNull android.media.MediaMetadata, @IntRange(from=1) int);
+ }
+
}
package android.media.session {
@@ -53,6 +57,10 @@
field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000
}
+ public static final class MediaSession.Token implements android.os.Parcelable {
+ method public int getUid();
+ }
+
public final class MediaSessionManager {
method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent);
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index ff3999f..8fae240 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -205,6 +205,7 @@
field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
+ field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
@@ -4277,6 +4278,14 @@
method @NonNull public android.media.HwAudioSource.Builder setAudioDeviceInfo(@NonNull android.media.AudioDeviceInfo);
}
+ public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
+ method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
+ }
+
+ public static interface MediaPlayer.OnImsRxNoticeListener {
+ method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
+ }
+
public final class MediaRecorder.AudioSource {
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int ECHO_REFERENCE = 1997; // 0x7cd
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public static final int HOTWORD = 1999; // 0x7cf
@@ -6812,6 +6821,8 @@
field public static final int BSS_CAPABILITY_CF_POLL_REQUEST = 8; // 0x8
field public static final int BSS_CAPABILITY_CHANNEL_AGILITY = 128; // 0x80
field public static final int BSS_CAPABILITY_DELAYED_BLOCK_ACK = 16384; // 0x4000
+ field public static final int BSS_CAPABILITY_DMG_ESS = 3; // 0x3
+ field public static final int BSS_CAPABILITY_DMG_IBSS = 1; // 0x1
field public static final int BSS_CAPABILITY_DSSS_OFDM = 8192; // 0x2000
field public static final int BSS_CAPABILITY_ESS = 1; // 0x1
field public static final int BSS_CAPABILITY_IBSS = 2; // 0x2
diff --git a/non-updatable-api/system-lint-baseline.txt b/non-updatable-api/system-lint-baseline.txt
index 395ddc1..4db55e7 100644
--- a/non-updatable-api/system-lint-baseline.txt
+++ b/non-updatable-api/system-lint-baseline.txt
@@ -6,7 +6,8 @@
BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
-
+ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
+
GenericException: android.app.prediction.AppPredictor#finalize():
GenericException: android.hardware.location.ContextHubClient#finalize():
@@ -181,6 +182,8 @@
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
+
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 1fe2760..949a0fa 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -53,6 +53,14 @@
<integer name="config_rightSystemBarZOrder">0</integer>
<integer name="config_bottomSystemBarZOrder">10</integer>
+ <!-- If set to true, the corresponding system bar will be hidden when Keyboard (IME) appears.
+ NOTE: hideBottomSystemBarKeyboard must not be overlaid directly here. To change its value,
+ overlay config_automotiveHideNavBarForKeyboard in framework/base/core/res/res. -->
+ <bool name="config_hideTopSystemBarForKeyboard">false</bool>
+ <bool name="config_hideBottomSystemBarForKeyboard">@*android:bool/config_automotiveHideNavBarForKeyboard</bool>
+ <bool name="config_hideLeftSystemBarForKeyboard">false</bool>
+ <bool name="config_hideRightSystemBarForKeyboard">false</bool>
+
<!-- Disable normal notification rendering; we handle that ourselves -->
<bool name="config_renderNotifications">false</bool>
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
index dadbc22..3af7507 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -30,7 +30,6 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
@@ -40,6 +39,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.KeyguardBouncer.Factory;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -66,7 +66,7 @@
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final ViewMediatorCallback mViewMediatorCallback;
private final CarNavigationBarController mCarNavigationBarController;
- private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ private final Factory mKeyguardBouncerFactory;
// Needed to instantiate mBouncer.
private final KeyguardBouncer.BouncerExpansionCallback
mExpansionCallback = new KeyguardBouncer.BouncerExpansionCallback() {
@@ -107,7 +107,7 @@
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
ViewMediatorCallback viewMediatorCallback,
CarNavigationBarController carNavigationBarController,
- KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
+ KeyguardBouncer.Factory keyguardBouncerFactory) {
super(R.id.keyguard_stub, overlayViewGlobalStateController);
@@ -118,7 +118,7 @@
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
mViewMediatorCallback = viewMediatorCallback;
mCarNavigationBarController = carNavigationBarController;
- mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
+ mKeyguardBouncerFactory = keyguardBouncerFactory;
registerUserSwitchedListener();
}
@@ -130,9 +130,8 @@
@Override
public void onFinishInflate() {
- mBouncer = mKeyguardBouncerComponentFactory
- .build(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback)
- .createKeyguardBouncer();
+ mBouncer = mKeyguardBouncerFactory
+ .create(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback);
mBiometricUnlockControllerLazy.get().setKeyguardViewController(this);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java
index aa6da89..2dc4756 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java
@@ -16,7 +16,7 @@
package com.android.systemui.car.navigationbar;
-import android.app.ActivityManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -97,27 +97,27 @@
* The StackInfo is expected to be supplied in order of recency and StackInfo will only be used
* for consideration if it has the same displayId as the CarNavigationButton.
*
- * @param stackInfoList of the currently running application
+ * @param taskInfoList of the currently running application
* @param validDisplay index of the valid display
*/
- protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList, int validDisplay) {
- ActivityManager.StackInfo validStackInfo = null;
- for (ActivityManager.StackInfo stackInfo : stackInfoList) {
+ protected void taskChanged(List<RootTaskInfo> taskInfoList, int validDisplay) {
+ RootTaskInfo validTaskInfo = null;
+ for (RootTaskInfo taskInfo : taskInfoList) {
// Find the first stack info with a topActivity in the primary display.
// TODO: We assume that CarFacetButton will launch an app only in the primary display.
// We need to extend the functionality to handle the multiple display properly.
- if (stackInfo.topActivity != null && stackInfo.displayId == validDisplay) {
- validStackInfo = stackInfo;
+ if (taskInfo.topActivity != null && taskInfo.displayId == validDisplay) {
+ validTaskInfo = taskInfo;
break;
}
}
- if (validStackInfo == null) {
+ if (validTaskInfo == null) {
// No stack was found that was on the same display as the buttons thus return
return;
}
- int displayId = validStackInfo.displayId;
+ int displayId = validTaskInfo.displayId;
mSelectedButtons.forEach(carNavigationButton -> {
if (carNavigationButton.getDisplayId() == displayId) {
@@ -126,7 +126,7 @@
});
mSelectedButtons.clear();
- HashSet<CarNavigationButton> selectedButtons = findSelectedButtons(validStackInfo);
+ HashSet<CarNavigationButton> selectedButtons = findSelectedButtons(validTaskInfo);
if (selectedButtons != null) {
selectedButtons.forEach(carNavigationButton -> {
@@ -141,10 +141,10 @@
/**
* Defaults to Display.DEFAULT_DISPLAY when no parameter is provided for the validDisplay.
*
- * @param stackInfoList
+ * @param taskInfoList
*/
- protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList) {
- taskChanged(stackInfoList, Display.DEFAULT_DISPLAY);
+ protected void taskChanged(List<RootTaskInfo> taskInfoList) {
+ taskChanged(taskInfoList, Display.DEFAULT_DISPLAY);
}
/**
@@ -171,12 +171,11 @@
mRegisteredViews.add(carNavigationButton);
}
- private HashSet<CarNavigationButton> findSelectedButtons(
- ActivityManager.StackInfo validStackInfo) {
- String packageName = validStackInfo.topActivity.getPackageName();
+ private HashSet<CarNavigationButton> findSelectedButtons(RootTaskInfo validTaskInfo) {
+ String packageName = validTaskInfo.topActivity.getPackageName();
HashSet<CarNavigationButton> selectedButtons =
- findButtonsByComponentName(validStackInfo.topActivity);
+ findButtonsByComponentName(validTaskInfo.topActivity);
if (selectedButtons == null) {
selectedButtons = mButtonsByPackage.get(packageName);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java
index d6216ba..f74bd4f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java
@@ -43,9 +43,9 @@
public void onTaskStackChanged() {
try {
mButtonSelectionStateController.taskChanged(
- ActivityTaskManager.getService().getAllStackInfos());
+ ActivityTaskManager.getService().getAllRootTaskInfos());
} catch (Exception e) {
- Log.e(TAG, "Getting StackInfo from activity manager failed", e);
+ Log.e(TAG, "Getting RootTaskInfo from activity task manager failed", e);
}
}
@@ -53,9 +53,9 @@
public void onTaskDisplayChanged(int taskId, int newDisplayId) {
try {
mButtonSelectionStateController.taskChanged(
- ActivityTaskManager.getService().getAllStackInfos());
+ ActivityTaskManager.getService().getAllRootTaskInfos());
} catch (Exception e) {
- Log.e(TAG, "Getting StackInfo from activity manager failed", e);
+ Log.e(TAG, "Getting RootTaskInfo from activity task manager failed", e);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
index bf8cda3..c7db3f6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
@@ -91,7 +91,11 @@
private ActivityManagerWrapper mActivityManagerWrapper;
// If the nav bar should be hidden when the soft keyboard is visible.
- private boolean mHideNavBarForKeyboard;
+ private boolean mHideTopBarForKeyboard;
+ private boolean mHideLeftBarForKeyboard;
+ private boolean mHideRightBarForKeyboard;
+ private boolean mHideBottomBarForKeyboard;
+
private boolean mBottomNavBarVisible;
// Nav bar views.
@@ -160,8 +164,13 @@
@Override
public void start() {
// Set initial state.
- mHideNavBarForKeyboard = mResources.getBoolean(
- com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+ mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+ mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
+ SystemBarConfigs.BOTTOM);
+ mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT);
+ mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
+ SystemBarConfigs.RIGHT);
+
mBottomNavBarVisible = false;
// Connect into the status bar manager service
@@ -411,17 +420,30 @@
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
boolean showImeSwitcher) {
- if (!mHideNavBarForKeyboard) {
- return;
- }
-
if (mContext.getDisplayId() != displayId) {
return;
}
boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
- mCarNavigationBarController.setBottomWindowVisibility(
- isKeyboardVisible ? View.GONE : View.VISIBLE);
+
+ if (mHideTopBarForKeyboard) {
+ mCarNavigationBarController.setTopWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+
+ if (mHideBottomBarForKeyboard) {
+ mCarNavigationBarController.setBottomWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+
+ if (mHideLeftBarForKeyboard) {
+ mCarNavigationBarController.setLeftWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+ if (mHideRightBarForKeyboard) {
+ mCarNavigationBarController.setRightWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
index 529083f4b..4fb5220 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
@@ -83,9 +83,7 @@
* Hides all system bars.
*/
public void hideBars() {
- if (mTopView != null) {
- mTopView.setVisibility(View.GONE);
- }
+ setTopWindowVisibility(View.GONE);
setBottomWindowVisibility(View.GONE);
setLeftWindowVisibility(View.GONE);
setRightWindowVisibility(View.GONE);
@@ -95,9 +93,7 @@
* Shows all system bars.
*/
public void showBars() {
- if (mTopView != null) {
- mTopView.setVisibility(View.VISIBLE);
- }
+ setTopWindowVisibility(View.VISIBLE);
setBottomWindowVisibility(View.VISIBLE);
setLeftWindowVisibility(View.VISIBLE);
setRightWindowVisibility(View.VISIBLE);
@@ -140,6 +136,11 @@
return mShowRight ? mNavigationBarViewFactory.getRightWindow() : null;
}
+ /** Toggles the top nav bar visibility. */
+ public boolean setTopWindowVisibility(@View.Visibility int visibility) {
+ return setWindowVisibility(getTopWindow(), visibility);
+ }
+
/** Toggles the bottom nav bar visibility. */
public boolean setBottomWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getBottomWindow(), visibility);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
index 1418ace..078196e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
@@ -100,6 +100,7 @@
checkEnabledBarsHaveUniqueBarTypes();
checkAllOverlappingBarsHaveDifferentZOrders();
checkSystemBarEnabledForNotificationPanel();
+ checkHideBottomBarForKeyboardConfigSync();
setInsetPaddingsForOverlappingCorners();
sortSystemBarSidesByZOrder();
}
@@ -124,6 +125,11 @@
}
}
+ protected boolean getHideForKeyboardBySide(@SystemBarSide int side) {
+ return mSystemBarConfigMap.get(side) != null
+ && mSystemBarConfigMap.get(side).getHideForKeyboard();
+ }
+
protected void insetSystemBar(@SystemBarSide int side, CarNavigationBarView view) {
if (mSystemBarConfigMap.get(side) == null) return;
@@ -213,6 +219,8 @@
com.android.internal.R.dimen.status_bar_height))
.setBarType(mResources.getInteger(R.integer.config_topSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideTopSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(TOP, topBarConfig);
}
@@ -226,6 +234,8 @@
.setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType))
.setZOrder(
mResources.getInteger(R.integer.config_bottomSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideBottomSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(BOTTOM, bottomBarConfig);
}
@@ -238,6 +248,8 @@
R.dimen.car_left_navigation_bar_width))
.setBarType(mResources.getInteger(R.integer.config_leftSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideLeftSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(LEFT, leftBarConfig);
}
@@ -250,6 +262,8 @@
R.dimen.car_right_navigation_bar_width))
.setBarType(mResources.getInteger(R.integer.config_rightSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideRightSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(RIGHT, rightBarConfig);
}
@@ -291,19 +305,37 @@
e.printStackTrace();
}
- if (!mTopNavBarEnabled && notificationPanelMediatorUsed.isAssignableFrom(
- TopNotificationPanelViewMediator.class)) {
+ if (!mTopNavBarEnabled && TopNotificationPanelViewMediator.class.isAssignableFrom(
+ notificationPanelMediatorUsed)) {
throw new RuntimeException(
"Top System Bar must be enabled to use " + notificationPanelMediatorName);
}
- if (!mBottomNavBarEnabled && notificationPanelMediatorUsed.isAssignableFrom(
- BottomNotificationPanelViewMediator.class)) {
+ if (!mBottomNavBarEnabled && BottomNotificationPanelViewMediator.class.isAssignableFrom(
+ notificationPanelMediatorUsed)) {
throw new RuntimeException("Bottom System Bar must be enabled to use "
+ notificationPanelMediatorName);
}
}
+ private void checkHideBottomBarForKeyboardConfigSync() throws RuntimeException {
+ if (mBottomNavBarEnabled) {
+ boolean actual = mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard);
+ boolean expected = mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+
+ if (actual != expected) {
+ throw new RuntimeException("config_hideBottomSystemBarForKeyboard must not be "
+ + "overlaid directly and should always refer to"
+ + "config_automotiveHideNavBarForKeyboard. However, their values "
+ + "currently do not sync. Set config_hideBottomSystemBarForKeyguard to "
+ + "@*android:bool/config_automotiveHideNavBarForKeyboard. To change its "
+ + "value, overlay config_automotiveHideNavBarForKeyboard in "
+ + "framework/base/core/res/res.");
+ }
+ }
+ }
+
private void setInsetPaddingsForOverlappingCorners() {
Map<@SystemBarSide Integer, Boolean> systemBarVisibilityOnInit =
getSystemBarsVisibilityOnInit();
@@ -410,14 +442,17 @@
private final int mBarType;
private final int mGirth;
private final int mZOrder;
+ private final boolean mHideForKeyboard;
private int[] mPaddings = new int[]{0, 0, 0, 0};
- private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder) {
+ private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder,
+ boolean hideForKeyboard) {
mSide = side;
mBarType = barType;
mGirth = girth;
mZOrder = zOrder;
+ mHideForKeyboard = hideForKeyboard;
}
private int getSide() {
@@ -436,6 +471,10 @@
return mZOrder;
}
+ private boolean getHideForKeyboard() {
+ return mHideForKeyboard;
+ }
+
private int[] getPaddings() {
return mPaddings;
}
@@ -473,6 +512,7 @@
private int mBarType;
private int mGirth;
private int mZOrder;
+ private boolean mHideForKeyboard;
private SystemBarConfigBuilder setSide(@SystemBarSide int side) {
mSide = side;
@@ -494,8 +534,13 @@
return this;
}
+ private SystemBarConfigBuilder setHideForKeyboard(boolean hide) {
+ mHideForKeyboard = hide;
+ return this;
+ }
+
private SystemBarConfig build() {
- return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder);
+ return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard);
}
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java
index eb32edb..f96ee0f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java
@@ -17,7 +17,7 @@
package com.android.systemui.car.sideloaded;
import android.annotation.NonNull;
-import android.app.ActivityManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
@@ -78,10 +78,10 @@
return false;
}
- boolean isSafe(@NonNull ActivityManager.StackInfo stackInfo) {
- ComponentName componentName = stackInfo.topActivity;
+ boolean isSafe(@NonNull RootTaskInfo taskInfo) {
+ ComponentName componentName = taskInfo.topActivity;
if (componentName == null) {
- Log.w(TAG, "Stack info does not have top activity: " + stackInfo.stackId);
+ Log.w(TAG, "Task info does not have top activity: " + taskInfo.taskId);
return false;
}
return isSafe(componentName.getPackageName());
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java
index c8c1a40..db7718b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java
@@ -16,8 +16,7 @@
package com.android.systemui.car.sideloaded;
-import android.app.ActivityManager;
-import android.app.ActivityManager.StackInfo;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.ComponentName;
@@ -56,15 +55,15 @@
public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
super.onTaskCreated(taskId, componentName);
- List<StackInfo> stackInfoList = mActivityTaskManager.getAllStackInfos();
- ActivityManager.StackInfo stackInfo = getStackInfo(stackInfoList, taskId);
- if (stackInfo == null) {
+ List<RootTaskInfo> taskInfoList = mActivityTaskManager.getAllRootTaskInfos();
+ RootTaskInfo taskInfo = getStackInfo(taskInfoList, taskId);
+ if (taskInfo == null) {
Log.e(TAG, "Stack info was not available for taskId: " + taskId);
return;
}
- if (!mSideLoadedAppDetector.isSafe(stackInfo)) {
- Display display = mDisplayManager.getDisplay(stackInfo.displayId);
+ if (!mSideLoadedAppDetector.isSafe(taskInfo)) {
+ Display display = mDisplayManager.getDisplay(taskInfo.displayId);
mSideLoadedAppStateController.onUnsafeTaskCreatedOnDisplay(display);
}
}
@@ -75,18 +74,18 @@
Display[] displays = mDisplayManager.getDisplays();
for (Display display : displays) {
- // Note that the stackInfoList is ordered by recency.
- List<StackInfo> stackInfoList =
- mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId());
+ // Note that the taskInfoList is ordered by recency.
+ List<RootTaskInfo> taskInfoList =
+ mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId());
- if (stackInfoList == null) {
+ if (taskInfoList == null) {
continue;
}
- StackInfo stackInfo = getTopVisibleStackInfo(stackInfoList);
- if (stackInfo == null) {
+ RootTaskInfo taskInfo = getTopVisibleStackInfo(taskInfoList);
+ if (taskInfo == null) {
continue;
}
- if (mSideLoadedAppDetector.isSafe(stackInfo)) {
+ if (mSideLoadedAppDetector.isSafe(taskInfo)) {
mSideLoadedAppStateController.onSafeTaskDisplayedOnDisplay(display);
} else {
mSideLoadedAppStateController.onUnsafeTaskDisplayedOnDisplay(display);
@@ -97,18 +96,17 @@
/**
* Returns stack info for a given taskId.
*/
- private ActivityManager.StackInfo getStackInfo(
- List<ActivityManager.StackInfo> stackInfoList, int taskId) {
- if (stackInfoList == null) {
+ private RootTaskInfo getStackInfo(List<RootTaskInfo> taskInfoList, int taskId) {
+ if (taskInfoList == null) {
return null;
}
- for (ActivityManager.StackInfo stackInfo : stackInfoList) {
- if (stackInfo.taskIds == null) {
+ for (RootTaskInfo taskInfo : taskInfoList) {
+ if (taskInfo.childTaskIds == null) {
continue;
}
- for (int stackTaskId : stackInfo.taskIds) {
- if (taskId == stackTaskId) {
- return stackInfo;
+ for (int taskTaskId : taskInfo.childTaskIds) {
+ if (taskId == taskTaskId) {
+ return taskInfo;
}
}
}
@@ -118,11 +116,10 @@
/**
* Returns the first visible stackInfo.
*/
- private ActivityManager.StackInfo getTopVisibleStackInfo(
- List<ActivityManager.StackInfo> stackInfoList) {
- for (ActivityManager.StackInfo stackInfo : stackInfoList) {
- if (stackInfo.visible) {
- return stackInfo;
+ private RootTaskInfo getTopVisibleStackInfo(List<RootTaskInfo> taskInfoList) {
+ for (RootTaskInfo taskInfo : taskInfoList) {
+ if (taskInfo.visible) {
+ return taskInfo;
}
}
return null;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java
index 5ef8aa1..1b1a118 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java
@@ -59,6 +59,8 @@
}
};
+ private boolean mUserLifecycleListenerRegistered = false;
+
private final CarUserManager.UserLifecycleListener mUserLifecycleListener =
new CarUserManager.UserLifecycleListener() {
@Override
@@ -100,9 +102,13 @@
* Clean up the controller and unregister receiver.
*/
public void removeAll() {
- mBroadcastDispatcher.unregisterReceiver(mUserUpdateReceiver);
- if (mCarUserManager != null) {
- mCarUserManager.removeListener(mUserLifecycleListener);
+ mUserNameView = null;
+ if (mUserLifecycleListenerRegistered) {
+ mBroadcastDispatcher.unregisterReceiver(mUserUpdateReceiver);
+ if (mCarUserManager != null) {
+ mCarUserManager.removeListener(mUserLifecycleListener);
+ }
+ mUserLifecycleListenerRegistered = false;
}
}
@@ -112,6 +118,7 @@
mCarUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE);
if (mCarUserManager != null) {
mCarUserManager.addListener(Runnable::run, mUserLifecycleListener);
+ mUserLifecycleListenerRegistered = true;
} else {
Log.e(TAG, "CarUserManager could not be obtained.");
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
index 63d4004..062ab41 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
@@ -36,7 +36,6 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarServiceProvider;
@@ -67,9 +66,7 @@
@Mock
private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener;
@Mock
- private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
- @Mock
- private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ private KeyguardBouncer.Factory mKeyguardBouncerFactory;
@Mock
private KeyguardBouncer mBouncer;
@@ -77,11 +74,10 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mKeyguardBouncerComponentFactory.build(
+ when(mKeyguardBouncerFactory.create(
any(ViewGroup.class),
any(KeyguardBouncer.BouncerExpansionCallback.class)))
- .thenReturn(mKeyguardBouncerComponent);
- when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+ .thenReturn(mBouncer);
mCarKeyguardViewController = new CarKeyguardViewController(
Handler.getMain(),
@@ -92,7 +88,7 @@
() -> mock(BiometricUnlockController.class),
mock(ViewMediatorCallback.class),
mock(CarNavigationBarController.class),
- mKeyguardBouncerComponentFactory
+ mKeyguardBouncerFactory
);
mCarKeyguardViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.sysui_overlay_window, /* root= */ null));
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java
index f623c26..bd017cd 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.ActivityManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -71,7 +71,7 @@
public void onTaskChanged_buttonDetectableByComponentName_selectsAssociatedButton() {
CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_component_name);
mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS);
- List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ List<RootTaskInfo> testStack = createTestStack(mComponentName);
testButton.setSelected(false);
mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
@@ -82,7 +82,7 @@
public void onTaskChanged_buttonDetectableByCategory_selectsAssociatedButton() {
CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_category);
mComponentName = new ComponentName(TEST_CATEGORY, TEST_CATEGORY_CLASS);
- List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ List<RootTaskInfo> testStack = createTestStack(mComponentName);
testButton.setSelected(false);
mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
@@ -93,7 +93,7 @@
public void onTaskChanged_buttonDetectableByPackage_selectsAssociatedButton() {
CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_package);
mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS);
- List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ List<RootTaskInfo> testStack = createTestStack(mComponentName);
testButton.setSelected(false);
mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
@@ -104,12 +104,12 @@
public void onTaskChanged_deselectsPreviouslySelectedButton() {
CarNavigationButton oldButton = mTestView.findViewById(R.id.detectable_by_component_name);
mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS);
- List<ActivityManager.StackInfo> oldStack = createTestStack(mComponentName);
+ List<RootTaskInfo> oldStack = createTestStack(mComponentName);
oldButton.setSelected(false);
mButtonSelectionStateController.taskChanged(oldStack, /* validDisplay= */ -1);
mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS);
- List<ActivityManager.StackInfo> newStack = createTestStack(mComponentName);
+ List<RootTaskInfo> newStack = createTestStack(mComponentName);
mButtonSelectionStateController.taskChanged(newStack, /* validDisplay= */ -1);
assertButtonUnselected(oldButton);
@@ -125,12 +125,12 @@
assertThat(button.getAlpha()).isEqualTo(CarNavigationButton.DEFAULT_UNSELECTED_ALPHA);
}
- private List<ActivityManager.StackInfo> createTestStack(ComponentName componentName) {
- ActivityManager.StackInfo validStackInfo = new ActivityManager.StackInfo();
+ private List<RootTaskInfo> createTestStack(ComponentName componentName) {
+ RootTaskInfo validStackInfo = new RootTaskInfo();
validStackInfo.displayId = -1; // No display is assigned to this test view
validStackInfo.topActivity = componentName;
- List<ActivityManager.StackInfo> testStack = new ArrayList<>();
+ List<RootTaskInfo> testStack = new ArrayList<>();
testStack.add(validStackInfo);
return testStack;
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
index 072358b..0c62f8b 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.car.navigationbar;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -32,7 +33,14 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarSystemUiTest;
+import com.android.systemui.car.notification.NotificationPanelViewController;
+import com.android.systemui.car.notification.NotificationPanelViewMediator;
+import com.android.systemui.car.notification.PowerManagerHelper;
+import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.Before;
import org.junit.Test;
@@ -54,8 +62,6 @@
private SystemBarConfigs mSystemBarConfigs;
@Mock
private Resources mResources;
- @Mock
- private CarNavigationBarView mCarNavigationBarView;
@Before
public void setUp() {
@@ -97,6 +103,43 @@
mSystemBarConfigs = new SystemBarConfigs(mResources);
}
+ @Test(expected = RuntimeException.class)
+ public void onInit_hideBottomSystemBarForKeyboardValueDoNotSync_throwsRuntimeException() {
+ when(mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard)).thenReturn(false);
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard)).thenReturn(
+ true);
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void onInit_topNotifPanelViewMediatorUsed_topBarEnabled_doesNotThrowException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(true);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ TestTopNotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void onInit_topNotifPanelViewMediatorUsed_topBarNotEnabled_throwsRuntimeException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ TestTopNotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void onInit_notificationPanelViewMediatorUsed_topBarNotEnabled_doesNotThrowException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ NotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
@Test
public void getTopSystemBarLayoutParams_topBarEnabled_returnsTopSystemBarLayoutParams() {
mSystemBarConfigs = new SystemBarConfigs(mResources);
@@ -117,6 +160,26 @@
}
@Test
+ public void getTopSystemBarHideForKeyboard_hideBarForKeyboard_returnsTrue() {
+ when(mResources.getBoolean(R.bool.config_hideTopSystemBarForKeyboard)).thenReturn(true);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+
+ boolean hideKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+
+ assertTrue(hideKeyboard);
+ }
+
+ @Test
+ public void getTopSystemBarHideForKeyboard_topBarNotEnabled_returnsFalse() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+
+ boolean hideKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+
+ assertFalse(hideKeyboard);
+ }
+
+ @Test
public void topSystemBarHasHigherZOrderThanHuns_topSystemBarIsNavigationBarPanelType() {
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
SystemBarConfigs.getHunZOrder() + 1);
@@ -198,5 +261,30 @@
when(mResources.getInteger(R.integer.config_bottomSystemBarZOrder)).thenReturn(10);
when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(2);
when(mResources.getInteger(R.integer.config_rightSystemBarZOrder)).thenReturn(3);
+
+ when(mResources.getBoolean(R.bool.config_hideTopSystemBarForKeyboard)).thenReturn(false);
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard)).thenReturn(
+ false);
+ when(mResources.getBoolean(R.bool.config_hideLeftSystemBarForKeyboard)).thenReturn(
+ false);
+ when(mResources.getBoolean(R.bool.config_hideRightSystemBarForKeyboard)).thenReturn(
+ false);
+ }
+
+ // Intentionally using a subclass of TopNotificationPanelViewMediator for testing purposes to
+ // ensure that OEM's will be able to implement and use their own NotificationPanelViewMediator.
+ private class TestTopNotificationPanelViewMediator extends
+ TopNotificationPanelViewMediator {
+ TestTopNotificationPanelViewMediator(
+ CarNavigationBarController carNavigationBarController,
+ NotificationPanelViewController notificationPanelViewController,
+ PowerManagerHelper powerManagerHelper,
+ BroadcastDispatcher broadcastDispatcher,
+ CarDeviceProvisionedController carDeviceProvisionedController,
+ ConfigurationController configurationController) {
+ super(carNavigationBarController, notificationPanelViewController, powerManagerHelper,
+ broadcastDispatcher, carDeviceProvisionedController, configurationController);
+ }
}
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java
index 421e210..bf9ac30 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java
@@ -23,7 +23,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-import android.app.ActivityManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
@@ -79,8 +79,8 @@
@Test
public void isSafe_systemApp_returnsTrue() throws Exception {
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = APP_PACKAGE_NAME;
@@ -89,13 +89,13 @@
when(mPackageManager.getApplicationInfoAsUser(eq(APP_PACKAGE_NAME), anyInt(), any()))
.thenReturn(applicationInfo);
- assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue();
+ assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue();
}
@Test
public void isSafe_updatedSystemApp_returnsTrue() throws Exception {
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = APP_PACKAGE_NAME;
@@ -104,7 +104,7 @@
when(mPackageManager.getApplicationInfoAsUser(eq(APP_PACKAGE_NAME), anyInt(), any()))
.thenReturn(applicationInfo);
- assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue();
+ assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue();
}
@Test
@@ -113,8 +113,8 @@
/* initiatingPackageSigningInfo= */null,
/* originatingPackageName= */ null,
/* installingPackageName= */ null);
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = APP_PACKAGE_NAME;
@@ -123,7 +123,7 @@
.thenReturn(applicationInfo);
when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo);
- assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue();
+ assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue();
}
@Test
@@ -132,8 +132,8 @@
/* initiatingPackageSigningInfo= */null,
/* originatingPackageName= */ null,
/* installingPackageName= */ null);
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = APP_PACKAGE_NAME;
@@ -142,7 +142,7 @@
.thenReturn(applicationInfo);
when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo);
- assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isFalse();
+ assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isFalse();
}
@Test
@@ -151,8 +151,8 @@
/* initiatingPackageSigningInfo= */null,
/* originatingPackageName= */ null,
/* installingPackageName= */ null);
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = APP_PACKAGE_NAME;
@@ -161,6 +161,6 @@
.thenReturn(applicationInfo);
when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo);
- assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isFalse();
+ assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isFalse();
}
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
index 67f222b..0b5f68f 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
@@ -21,7 +21,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.ActivityManager.StackInfo;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.hardware.display.DisplayManager;
@@ -81,22 +81,22 @@
int displayId = 123;
ComponentName componentName = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
- StackInfo stackInfo1 = createTask(1, /* isVisible= */ true);
- stackInfo1.taskIds = new int[] { 11, 22, 33 };
+ RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ true);
+ taskInfo1.childTaskIds = new int[] { 11, 22, 33 };
- StackInfo stackInfo2 = createTask(2, /* isVisible= */ true);
- stackInfo2.taskIds = new int[] { 111, 222, 333, taskId };
- stackInfo2.displayId = displayId;
+ RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true);
+ taskInfo2.childTaskIds = new int[] { 111, 222, 333, taskId };
+ taskInfo2.displayId = displayId;
- List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2);
+ List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2);
- when(mActivityTaskManager.getAllStackInfos()).thenReturn(stackInfoList);
- when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true);
+ when(mActivityTaskManager.getAllRootTaskInfos()).thenReturn(taskInfoList);
+ when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true);
mSideLoadedAppListener.onTaskCreated(taskId, componentName);
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1);
- verify(mSideLoadedAppDetector).isSafe(stackInfo2);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo2);
verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any());
verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any());
@@ -109,23 +109,23 @@
int displayId = 123;
ComponentName componentName = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME);
- StackInfo stackInfo1 = createTask(1, /* isVisible= */ true);
- stackInfo1.taskIds = new int[] { 11, 22, 33 };
- StackInfo stackInfo2 = createTask(2, /* isVisible= */ true);
- stackInfo2.taskIds = new int[] { 111, 222, 333, taskId };
- stackInfo2.displayId = displayId;
- List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2);
+ RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ true);
+ taskInfo1.childTaskIds = new int[] { 11, 22, 33 };
+ RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true);
+ taskInfo2.childTaskIds = new int[] { 111, 222, 333, taskId };
+ taskInfo2.displayId = displayId;
+ List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2);
Display display = createDisplay(displayId);
- when(mActivityTaskManager.getAllStackInfos()).thenReturn(stackInfoList);
- when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(false);
+ when(mActivityTaskManager.getAllRootTaskInfos()).thenReturn(taskInfoList);
+ when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(false);
when(mDisplayManager.getDisplay(displayId)).thenReturn(display);
mSideLoadedAppListener.onTaskCreated(taskId, componentName);
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1);
- verify(mSideLoadedAppDetector).isSafe(stackInfo2);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo2);
verify(mSideLoadedAppStateController).onUnsafeTaskCreatedOnDisplay(display);
verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any());
@@ -135,21 +135,21 @@
@Test
public void onTaskStackChanged_safeTask_callsSafeTaskDisplayed() throws Exception {
Display display = createDisplay(123);
- StackInfo stackInfo1 = createTask(1, /* isVisible= */ false);
- StackInfo stackInfo2 = createTask(2, /* isVisible= */ true);
- StackInfo stackInfo3 = createTask(3, /* isVisible= */ true);
- List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2, stackInfo3);
+ RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false);
+ RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true);
+ RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true);
+ List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2, taskInfo3);
- when(mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId()))
- .thenReturn(stackInfoList);
- when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true);
+ when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId()))
+ .thenReturn(taskInfoList);
+ when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true);
when(mDisplayManager.getDisplays()).thenReturn(new Display[] { display });
mSideLoadedAppListener.onTaskStackChanged();
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1);
- verify(mSideLoadedAppDetector).isSafe(stackInfo2);
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo2);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3);
verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any());
verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display);
@@ -159,21 +159,21 @@
@Test
public void onTaskStackChanged_unsafeTask_callsUnsafeTaskDisplayed() throws Exception {
Display display = createDisplay(123);
- StackInfo stackInfo1 = createTask(1, /* isVisible= */ false);
- StackInfo stackInfo2 = createTask(2, /* isVisible= */ true);
- StackInfo stackInfo3 = createTask(3, /* isVisible= */ true);
- List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2, stackInfo3);
+ RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false);
+ RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true);
+ RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true);
+ List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2, taskInfo3);
- when(mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId()))
- .thenReturn(stackInfoList);
- when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(false);
+ when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId()))
+ .thenReturn(taskInfoList);
+ when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(false);
when(mDisplayManager.getDisplays()).thenReturn(new Display[] { display });
mSideLoadedAppListener.onTaskStackChanged();
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1);
- verify(mSideLoadedAppDetector).isSafe(stackInfo2);
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo2);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3);
verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any());
verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any());
@@ -183,40 +183,40 @@
@Test
public void onTaskStackChanged_multiDisplay_callsTasksDisplayed() throws Exception {
Display display1 = createDisplay(1);
- StackInfo stackInfo1 = createTask(1, /* isVisible= */ false);
- StackInfo stackInfo2 = createTask(2, /* isVisible= */ true);
- StackInfo stackInfo3 = createTask(3, /* isVisible= */ true);
- List<StackInfo> display1Stack = Arrays.asList(stackInfo1, stackInfo2, stackInfo3);
+ RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false);
+ RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true);
+ RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true);
+ List<RootTaskInfo> display1Tasks = Arrays.asList(taskInfo1, taskInfo2, taskInfo3);
Display display2 = createDisplay(2);
- StackInfo stackInfo4 = createTask(4, /* isVisible= */ true);
- List<StackInfo> display2Stack = Collections.singletonList(stackInfo4);
+ RootTaskInfo taskInfo4 = createTask(4, /* isVisible= */ true);
+ List<RootTaskInfo> display2Tasks = Collections.singletonList(taskInfo4);
Display display3 = createDisplay(3);
- StackInfo stackInfo5 = createTask(5, /* isVisible= */ true);
- List<StackInfo> display3Stack = Collections.singletonList(stackInfo5);
+ RootTaskInfo taskInfo5 = createTask(5, /* isVisible= */ true);
+ List<RootTaskInfo> display3Tasks = Collections.singletonList(taskInfo5);
- when(mActivityTaskManager.getAllStackInfosOnDisplay(display1.getDisplayId()))
- .thenReturn(display1Stack);
- when(mActivityTaskManager.getAllStackInfosOnDisplay(display2.getDisplayId()))
- .thenReturn(display2Stack);
- when(mActivityTaskManager.getAllStackInfosOnDisplay(display3.getDisplayId()))
- .thenReturn(display3Stack);
+ when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display1.getDisplayId()))
+ .thenReturn(display1Tasks);
+ when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display2.getDisplayId()))
+ .thenReturn(display2Tasks);
+ when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display3.getDisplayId()))
+ .thenReturn(display3Tasks);
- when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true);
- when(mSideLoadedAppDetector.isSafe(stackInfo4)).thenReturn(false);
- when(mSideLoadedAppDetector.isSafe(stackInfo5)).thenReturn(true);
+ when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true);
+ when(mSideLoadedAppDetector.isSafe(taskInfo4)).thenReturn(false);
+ when(mSideLoadedAppDetector.isSafe(taskInfo5)).thenReturn(true);
when(mDisplayManager.getDisplays())
.thenReturn(new Display[] { display1, display2, display3});
mSideLoadedAppListener.onTaskStackChanged();
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1);
- verify(mSideLoadedAppDetector).isSafe(stackInfo2);
- verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3);
- verify(mSideLoadedAppDetector).isSafe(stackInfo4);
- verify(mSideLoadedAppDetector).isSafe(stackInfo5);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo2);
+ verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo4);
+ verify(mSideLoadedAppDetector).isSafe(taskInfo5);
verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any());
verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display1);
@@ -234,10 +234,10 @@
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
- private StackInfo createTask(int id, boolean isVisible) {
- StackInfo stackInfo = new StackInfo();
- stackInfo.stackId = id;
- stackInfo.visible = isVisible;
- return stackInfo;
+ private RootTaskInfo createTask(int id, boolean isVisible) {
+ RootTaskInfo taskInfo = new RootTaskInfo();
+ taskInfo.taskId = id;
+ taskInfo.visible = isVisible;
+ return taskInfo;
}
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java
index 8f9e56e..ac7edd3 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java
@@ -109,6 +109,13 @@
}
@Test
+ public void removeAll_withNoRegisteredListener_doesNotUnregister() {
+ mUserNameViewController.removeAll();
+
+ verifyZeroInteractions(mCarUserManager);
+ }
+
+ @Test
public void userLifecycleListener_onUserSwitchLifecycleEvent_updatesUserNameView() {
ArgumentCaptor<CarUserManager.UserLifecycleListener> userLifecycleListenerArgumentCaptor =
ArgumentCaptor.forClass(CarUserManager.UserLifecycleListener.class);
diff --git a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
index 47eeb83..2b9fa41 100644
--- a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="keyguard_description" msgid="8582605799129954556">"Geef je wachtwoord op en ga door naar \'Dynamische systeemupdates\'"</string>
- <string name="notification_install_completed" msgid="6252047868415172643">"Dynamisch systeem is gereed. Start je apparaat opnieuw op om het te gebruiken."</string>
+ <string name="notification_install_completed" msgid="6252047868415172643">"Dynamisch systeem is klaar. Start je apparaat opnieuw op om het te gebruiken."</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"Installatie wordt uitgevoerd"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"Installatie mislukt"</string>
<string name="notification_image_validation_failed" msgid="2720357826403917016">"Valideren van afbeelding mislukt. Installatie afbreken."</string>
diff --git a/packages/InputDevices/res/raw/keyboard_layout_czech_qwerty.kcm b/packages/InputDevices/res/raw/keyboard_layout_czech_qwerty.kcm
new file mode 100644
index 0000000..457d4da
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_czech_qwerty.kcm
@@ -0,0 +1,365 @@
+# Copyright (C) 2020 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.
+
+#
+# Czech (EU - qwerty) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: ';'
+ base: ';'
+ shift: '\u00b0'
+ ralt: '\u0060'
+ shift+ralt: '\u007e'
+}
+
+key 1 {
+ label: '1'
+ base: '+'
+ shift: '1'
+ ralt: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '\u011b'
+ capslock: '\u011a'
+ shift: '2'
+ ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '\u0161'
+ capslock: '\u0160'
+ shift: '3'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '\u010d'
+ capslock: '\u010c'
+ shift: '4'
+ ralt: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '\u0159'
+ capslock: '\u0158'
+ shift: '5'
+ ralt: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '\u017e'
+ capslock: '\u017d'
+ shift: '6'
+ ralt: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '\u00fd'
+ capslock: '\u00dd'
+ shift: '7'
+ ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '\u00e1'
+ capslock: '\u00c1'
+ shift: '8'
+ ralt: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '\u00ed'
+ capslock: '\u00cd'
+ shift: '9'
+ ralt: '('
+}
+
+key 0 {
+ label: '0'
+ base: '\u00e9'
+ capslock: '\u00c9'
+ shift: '0'
+ ralt: ')'
+}
+
+key MINUS {
+ label: '='
+ base: '='
+ shift: '%'
+ ralt: '-'
+ ralt+shift: '_'
+}
+
+key EQUALS {
+ label: '\u00b4'
+ base: '\u0301'
+ shift: '\u030c'
+ ralt: '='
+ ralt+shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00fa'
+ base: '\u00fa'
+ capslock: '\u00da'
+ shift: '/'
+ ralt: '['
+ ralt+shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ')'
+ base: ')'
+ shift: '('
+ ralt: ']'
+ ralt+shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u016f'
+ base: '\u016f'
+ capslock: '\u016e'
+ shift: '"'
+ ralt: ';'
+ ralt+shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\u00a7'
+ base: '\u00a7'
+ shift: '!'
+ ralt: '\u00a4'
+ ralt+shift: '\u005e'
+}
+
+key BACKSLASH {
+ label: '\u0308'
+ base: '\u0308'
+ shift: '\''
+ ralt: '\\'
+ ralt+shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+ ralt: '\u00df'
+ shift+ralt: '\u02dd'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+ ralt: '@'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+ ralt: '\u00b5'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '?'
+ ralt: '<'
+ shift+ralt: '\u00d7'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+ ralt: '>'
+ shift+ralt: '\u00f7'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '/'
+ ralt+shift: '?'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 9878146..e95a159 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -75,6 +75,9 @@
<!-- Czech keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_czech">Czech</string>
+ <!-- Czech qwerty keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_czech_qwerty">Czech QWERTY style</string>
+
<!-- Estonian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_estonian">Estonian</string>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 0d7a13b..aa599ae 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -92,6 +92,10 @@
android:label="@string/keyboard_layout_czech"
android:keyboardLayout="@raw/keyboard_layout_czech" />
+ <keyboard-layout android:name="keyboard_layout_czech_qwerty"
+ android:label="@string/keyboard_layout_czech_qwerty"
+ android:keyboardLayout="@raw/keyboard_layout_czech_qwerty" />
+
<keyboard-layout android:name="keyboard_layout_estonian"
android:label="@string/keyboard_layout_estonian"
android:keyboardLayout="@raw/keyboard_layout_estonian" />
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index 108c86f..d3a9589 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="7488448184431507488">"Pakket-installatie"</string>
<string name="install" msgid="711829760615509273">"Installeren"</string>
- <string name="done" msgid="6632441120016885253">"Gereed"</string>
+ <string name="done" msgid="6632441120016885253">"Klaar"</string>
<string name="cancel" msgid="1018267193425558088">"Annuleren"</string>
<string name="installing" msgid="4921993079741206516">"Installeren…"</string>
<string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeren…"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 8f71509..7f6237d 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -212,7 +212,7 @@
<string name="adb_wireless_settings" msgid="2295017847215680229">"Адладка па Wi-Fi"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Каб праглядаць і выкарыстоўваць даступныя прылады, уключыце адладку па Wi-Fi"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Спалучыць прыладу з дапамогай QR-кода"</string>
- <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кода"</string>
+ <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кодаў"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Спалучыць прыладу з дапамогай кода спалучэння"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Спалучаць новыя прылады з дапамогай шасцізначнага кода"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Спалучаныя прылады"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 7c2a0fd..775cd15 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -187,7 +187,7 @@
<item msgid="97587758561106269">"Isključeno"</item>
<item msgid="7126170197336963369">"Međuspremnici svih zapisnika"</item>
<item msgid="7167543126036181392">"Međuspremnici svih zapisnika osim radija"</item>
- <item msgid="5135340178556563979">"samo međuspremnik zapisnika kernela"</item>
+ <item msgid="5135340178556563979">"samo međumemorija zapisnika kernela"</item>
</string-array>
<string-array name="window_animation_scale_entries">
<item msgid="2675263395797191850">"Animacija isključena"</item>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index fbd8876..dd2aa3b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1777,6 +1777,9 @@
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
SecureSettingsProto.Accessibility.HIGH_TEXT_CONTRAST_ENABLED);
dumpSetting(s, p,
+ Settings.Secure.FORCE_BOLD_TEXT,
+ SecureSettingsProto.FORCE_BOLD_TEXT);
+ dumpSetting(s, p,
Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
SecureSettingsProto.Accessibility.LARGE_POINTER_ICON);
dumpSetting(s, p,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 319b44c..190015c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -217,6 +217,9 @@
<!-- Permission needed for CTS test - UnsupportedErrorDialogTests -->
<uses-permission android:name="android.permission.RESET_APP_ERRORS" />
+ <!-- Permission needed for CTS test - CtsSystemUiTestCases:PipNotificationTests -->
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
+
<!-- Permission needed to run keyguard manager tests in CTS -->
<uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" />
diff --git a/packages/SimAppDialog/Android.bp b/packages/SimAppDialog/Android.bp
index 1c680bb..176035f 100644
--- a/packages/SimAppDialog/Android.bp
+++ b/packages/SimAppDialog/Android.bp
@@ -7,8 +7,7 @@
static_libs: [
"androidx.legacy_legacy-support-v4",
- "setupcompat",
- "setupdesign",
+ "setup-wizard-lib",
],
resource_dirs: ["res"],
diff --git a/packages/SimAppDialog/AndroidManifest.xml b/packages/SimAppDialog/AndroidManifest.xml
index e7368f3..873f6c5 100644
--- a/packages/SimAppDialog/AndroidManifest.xml
+++ b/packages/SimAppDialog/AndroidManifest.xml
@@ -23,7 +23,7 @@
android:name=".InstallCarrierAppActivity"
android:exported="true"
android:permission="android.permission.NETWORK_SETTINGS"
- android:theme="@style/SudThemeGlif.Light">
+ android:theme="@style/SuwThemeGlif.Light">
</activity>
</application>
</manifest>
diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
index 68113db..12f9bb6 100644
--- a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
+++ b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
@@ -14,17 +14,18 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.google.android.setupdesign.GlifLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_signal_cellular_alt_rounded"
- app:sucHeaderText="@string/install_carrier_app_title">
+ app:suwHeaderText="@string/install_carrier_app_title"
+ app:suwFooter="@layout/install_carrier_app_footer">
<LinearLayout
- style="@style/SudContentFrame"
+ style="@style/SuwContentFrame"
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -32,12 +33,12 @@
<TextView
android:id="@+id/install_carrier_app_description"
- style="@style/SudDescription.Glif"
+ style="@style/SuwDescription.Glif"
android:text="@string/install_carrier_app_description_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
- <com.google.android.setupdesign.view.FillContentLayout
+ <com.android.setupwizardlib.view.FillContentLayout
android:id="@+id/illo_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -46,12 +47,12 @@
<ImageView
android:src="@drawable/illo_sim_app_dialog"
- style="@style/SudContentIllustration"
+ style="@style/SuwContentIllustration"
android:contentDescription="@string/install_carrier_app_image_content_description"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- </com.google.android.setupdesign.view.FillContentLayout>
- </LinearLayout>
+ </com.android.setupwizardlib.view.FillContentLayout>
+</LinearLayout>
-</com.google.android.setupdesign.GlifLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml
new file mode 100644
index 0000000..10dcb77
--- /dev/null
+++ b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<com.android.setupwizardlib.view.ButtonBarLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/footer"
+ style="@style/SuwGlifButtonBar.Stackable"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/skip_button"
+ style="@style/SuwGlifButton.Secondary"
+ android:text="@string/install_carrier_app_defer_action"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/download_button"
+ style="@style/SuwGlifButton.Primary"
+ android:text="@string/install_carrier_app_download_action"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</com.android.setupwizardlib.view.ButtonBarLayout>
diff --git a/packages/SimAppDialog/res/values/styles.xml b/packages/SimAppDialog/res/values/styles.xml
deleted file mode 100644
index 824e380..0000000
--- a/packages/SimAppDialog/res/values/styles.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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.
--->
-<resources>
-
- <style name="SetupWizardPartnerResource">
- <!-- Disable to use partner overlay theme for outside setupwizard flow. -->
- <item name="sucUsePartnerResource">false</item>
- <!-- Enable heavy theme style inside setupwizard flow. -->
- <item name="sudUsePartnerHeavyTheme">true</item>
- </style>
-
-</resources>
diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
index 0b6f9bb..abe82a8 100644
--- a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
+++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
@@ -17,17 +17,14 @@
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Bundle;
import android.sysprop.SetupWizardProperties;
import android.text.TextUtils;
import android.view.View;
+import android.widget.Button;
import android.widget.TextView;
-import com.google.android.setupcompat.template.FooterBarMixin;
-import com.google.android.setupcompat.template.FooterButton;
-import com.google.android.setupdesign.GlifLayout;
-import com.google.android.setupdesign.util.ThemeResolver;
+import com.android.setupwizardlib.util.WizardManagerHelper;
/**
* Activity that gives a user the choice to download the SIM app or defer until a later time
@@ -38,7 +35,7 @@
* Can display the carrier app name if its passed into the intent with key
* {@link #BUNDLE_KEY_CARRIER_NAME}
*/
-public class InstallCarrierAppActivity extends Activity {
+public class InstallCarrierAppActivity extends Activity implements View.OnClickListener {
/**
* Key for the carrier app name that will be displayed as the app to download. If unset, a
* default description will be used
@@ -53,33 +50,20 @@
protected void onCreate(Bundle icicle) {
// Setup theme for aosp/pixel
setTheme(
- new ThemeResolver.Builder()
- .setDefaultTheme(R.style.SudThemeGlifV3_Light)
- .build()
- .resolve(SetupWizardProperties.theme().orElse(""),
- /* suppressDayNight= */ false));
+ WizardManagerHelper.getThemeRes(
+ SetupWizardProperties.theme().orElse(""),
+ R.style.SuwThemeGlif_Light
+ )
+ );
super.onCreate(icicle);
setContentView(R.layout.install_carrier_app_activity);
- GlifLayout layout = findViewById(R.id.setup_wizard_layout);
- FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
- mixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.install_carrier_app_defer_action)
- .setListener(this::onSkipButtonClick)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build());
+ Button notNowButton = findViewById(R.id.skip_button);
+ notNowButton.setOnClickListener(this);
- mixin.setPrimaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.install_carrier_app_download_action)
- .setListener(this::onDownloadButtonClick)
- .setButtonType(FooterButton.ButtonType.OTHER)
- .setTheme(R.style.SudGlifButton_Primary)
- .build());
-
+ Button downloadButton = findViewById(R.id.download_button);
+ downloadButton.setOnClickListener(this);
// Show/hide illo depending on whether one was provided in a resource overlay
boolean showIllo = getResources().getBoolean(R.bool.show_sim_app_dialog_illo);
@@ -98,17 +82,15 @@
}
@Override
- protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
- theme.applyStyle(R.style.SetupWizardPartnerResource, true);
- super.onApplyThemeResource(theme, resid, first);
- }
-
- protected void onSkipButtonClick(View view) {
- finish(DEFER_RESULT);
- }
-
- protected void onDownloadButtonClick(View view) {
- finish(DOWNLOAD_RESULT);
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.skip_button:
+ finish(DEFER_RESULT);
+ break;
+ case R.id.download_button:
+ finish(DOWNLOAD_RESULT);
+ break;
+ }
}
private void finish(int resultCode) {
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 211a27c..0a36dae 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1067,6 +1067,8 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold Power button to see new controls"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
- <string name="one_handed_tutorial_title" msgid="6312198435090726656">"Using one-handed mode"</string>
- <string name="one_handed_tutorial_description" msgid="7674850272340517174">"To exit, swipe up from the bottom of the screen or tap anywhere above the app"</string>
+ <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
+ <skip />
+ <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4e9347c..79c2fbd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -395,7 +395,7 @@
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Conectado (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="5257299852322475780">"Compartir conexión"</string>
- <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Zona Wi-Fi"</string>
+ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Punto de acceso"</string>
<string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activando…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos activado"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
@@ -660,7 +660,7 @@
<string name="alarm_template" msgid="2234991538018805736">"a las <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Ajustes rápidos, <xliff:g id="TITLE">%s</xliff:g>."</string>
- <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Zona Wi-Fi"</string>
+ <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Punto de acceso"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index b02be5d..01d3fec 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -390,7 +390,7 @@
<string name="quick_settings_inversion_label" msgid="5078769633069667698">"Kleuren omkeren"</string>
<string name="quick_settings_color_space_label" msgid="537528291083575559">"Modus voor kleurcorrectie"</string>
<string name="quick_settings_more_settings" msgid="2878235926753776694">"Meer instellingen"</string>
- <string name="quick_settings_done" msgid="2163641301648855793">"Gereed"</string>
+ <string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"Verbonden"</string>
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Verbonden, batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"Verbinding maken…"</string>
@@ -692,7 +692,7 @@
<string name="notification_channel_silenced" msgid="1995937493874511359">"Deze meldingen worden zonder geluid weergegeven"</string>
<string name="notification_channel_unsilenced" msgid="94878840742161152">"Deze meldingen stellen je op de hoogte"</string>
<string name="inline_blocking_helper" msgid="2891486013649543452">"Meestal sluit je deze meldingen. \nWil je ze blijven weergeven?"</string>
- <string name="inline_done_button" msgid="6043094985588909584">"Gereed"</string>
+ <string name="inline_done_button" msgid="6043094985588909584">"Klaar"</string>
<string name="inline_ok_button" msgid="603075490581280343">"Toepassen"</string>
<string name="inline_keep_showing" msgid="8736001253507073497">"Deze meldingen blijven weergeven?"</string>
<string name="inline_stop_button" msgid="2453460935438696090">"Meldingen stoppen"</string>
@@ -747,7 +747,7 @@
<string name="notification_channel_switch_accessibility" msgid="8979885820432540252">"Meldingen van dit kanaal toestaan"</string>
<string name="notification_more_settings" msgid="4936228656989201793">"Meer instellingen"</string>
<string name="notification_app_settings" msgid="8963648463858039377">"Aanpassen"</string>
- <string name="notification_done" msgid="6215117625922713976">"Gereed"</string>
+ <string name="notification_done" msgid="6215117625922713976">"Klaar"</string>
<string name="inline_undo" msgid="9026953267645116526">"Ongedaan maken"</string>
<string name="demote" msgid="6225813324237153980">"Deze melding markeren als geen gesprek"</string>
<string name="notification_conversation_favorite" msgid="1905240206975921907">"Belangrijk gesprek"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1c3fba2..ab09a96 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -560,9 +560,6 @@
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
- <!-- Allow one handed to enable round corner -->
- <bool name="config_one_handed_enable_round_corner">true</bool>
-
<!-- Show a separate icon for low and high volume on the volume dialog -->
<bool name="config_showLowMediaVolumeIcon">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 76c61fb..875fe14 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1366,8 +1366,4 @@
<dimen name="config_rounded_mask_size">@*android:dimen/rounded_corner_radius</dimen>
<dimen name="config_rounded_mask_size_top">@*android:dimen/rounded_corner_radius_top</dimen>
<dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
-
- <!-- One-Handed Mode -->
- <!-- Threshold for dragging distance to enable one-handed mode -->
- <dimen name="gestures_onehanded_drag_threshold">20dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e58bf3b..cca70f9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2799,9 +2799,4 @@
<string name="udfps_hbm_enable_command" translatable="false"></string>
<!-- Device-specific payload for disabling the high-brightness mode -->
<string name="udfps_hbm_disable_command" translatable="false"></string>
-
- <!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
- <string name="one_handed_tutorial_title">Using one-handed mode</string>
- <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
- <string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index d64bf77..067ac9e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -153,12 +153,9 @@
}
}
+ @Deprecated
public void setPipVisibility(final boolean visible) {
- try {
- WindowManagerGlobal.getWindowManagerService().setPipVisibility(visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach window manager", e);
- }
+ // To be removed
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 57b3761..08e9cf6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -16,32 +16,11 @@
package com.android.keyguard;
-import android.app.ActivityManager;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
import android.graphics.Canvas;
-import android.media.AudioManager;
-import android.os.SystemClock;
-import android.service.trust.TrustAgentService;
-import android.telephony.TelephonyManager;
import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
import android.widget.FrameLayout;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-
-import java.io.File;
-
/**
* Base class for keyguard view. {@link #reset} is where you should
* reset the state of your view. Use the {@link KeyguardViewCallback} via
@@ -51,59 +30,10 @@
* Handles intercepting of media keys that still work when the keyguard is
* showing.
*/
-public class KeyguardHostView extends FrameLayout implements SecurityCallback {
+public class KeyguardHostView extends FrameLayout {
- private AudioManager mAudioManager;
- private TelephonyManager mTelephonyManager = null;
protected ViewMediatorCallback mViewMediatorCallback;
- protected LockPatternUtils mLockPatternUtils;
- private OnDismissAction mDismissAction;
- private Runnable mCancelAction;
- private final KeyguardUpdateMonitorCallback mUpdateCallback =
- new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onUserSwitchComplete(int userId) {
- getSecurityContainer().showPrimarySecurityScreen(false /* turning off */);
- }
-
- @Override
- public void onTrustGrantedWithFlags(int flags, int userId) {
- if (userId != KeyguardUpdateMonitor.getCurrentUser()) return;
- if (!isAttachedToWindow()) return;
- boolean bouncerVisible = isVisibleToUser();
- boolean initiatedByUser =
- (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0;
- boolean dismissKeyguard =
- (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0;
-
- if (initiatedByUser || dismissKeyguard) {
- if (mViewMediatorCallback.isScreenOn() && (bouncerVisible || dismissKeyguard)) {
- if (!bouncerVisible) {
- // The trust agent dismissed the keyguard without the user proving
- // that they are present (by swiping up to show the bouncer). That's fine if
- // the user proved presence via some other way to the trust agent.
- Log.i(TAG, "TrustAgent dismissed Keyguard.");
- }
- dismiss(false /* authenticated */, userId,
- /* bypassSecondaryLockScreen */ false);
- } else {
- mViewMediatorCallback.playTrustedSound();
- }
- }
- }
- };
-
- // Whether the volume keys should be handled by keyguard. If true, then
- // they will be handled here for specific media types such as music, otherwise
- // the audio service will bring up the volume dialog.
- private static final boolean KEYGUARD_MANAGES_VOLUME = false;
- public static final boolean DEBUG = KeyguardConstants.DEBUG;
- private static final String TAG = "KeyguardViewBase";
-
- @VisibleForTesting
- protected KeyguardSecurityContainer mSecurityContainer;
public KeyguardHostView(Context context) {
this(context, null);
@@ -111,7 +41,6 @@
public KeyguardHostView(Context context, AttributeSet attrs) {
super(context, attrs);
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateCallback);
}
@Override
@@ -122,337 +51,7 @@
}
}
- /**
- * Sets an action to run when keyguard finishes.
- *
- * @param action
- */
- public void setOnDismissAction(OnDismissAction action, Runnable cancelAction) {
- if (mCancelAction != null) {
- mCancelAction.run();
- mCancelAction = null;
- }
- mDismissAction = action;
- mCancelAction = cancelAction;
- }
-
- public boolean hasDismissActions() {
- return mDismissAction != null || mCancelAction != null;
- }
-
- public void cancelDismissAction() {
- setOnDismissAction(null, null);
- }
-
- @Override
- protected void onFinishInflate() {
- mSecurityContainer =
- findViewById(R.id.keyguard_security_container);
- mLockPatternUtils = new LockPatternUtils(mContext);
- mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
- mSecurityContainer.setSecurityCallback(this);
- mSecurityContainer.showPrimarySecurityScreen(false);
- }
-
- /**
- * Called when the view needs to be shown.
- */
- public void showPrimarySecurityScreen() {
- if (DEBUG) Log.d(TAG, "show()");
- mSecurityContainer.showPrimarySecurityScreen(false);
- }
-
- public KeyguardSecurityView getCurrentSecurityView() {
- return mSecurityContainer != null ? mSecurityContainer.getCurrentSecurityView() : null;
- }
-
- /**
- * Show a string explaining why the security view needs to be solved.
- *
- * @param reason a flag indicating which string should be shown, see
- * {@link KeyguardSecurityView#PROMPT_REASON_NONE},
- * {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
- * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
- * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
- */
- public void showPromptReason(int reason) {
- mSecurityContainer.showPromptReason(reason);
- }
-
- public void showMessage(CharSequence message, ColorStateList colorState) {
- mSecurityContainer.showMessage(message, colorState);
- }
-
- public void showErrorMessage(CharSequence message) {
- showMessage(message, Utils.getColorError(mContext));
- }
-
- /**
- * Dismisses the keyguard by going to the next screen or making it gone.
- * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
- * @return True if the keyguard is done.
- */
- public boolean dismiss(int targetUserId) {
- return dismiss(false, targetUserId, false);
- }
-
- public boolean handleBackKey() {
- if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
- mSecurityContainer.dismiss(false, KeyguardUpdateMonitor.getCurrentUser());
- return true;
- }
- return false;
- }
-
- protected KeyguardSecurityContainer getSecurityContainer() {
- return mSecurityContainer;
- }
-
- @Override
- public boolean dismiss(boolean authenticated, int targetUserId,
- boolean bypassSecondaryLockScreen) {
- return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId,
- bypassSecondaryLockScreen);
- }
-
- /**
- * Authentication has happened and it's time to dismiss keyguard. This function
- * should clean up and inform KeyguardViewMediator.
- *
- * @param strongAuth whether the user has authenticated with strong authentication like
- * pattern, password or PIN but not by trust agents or fingerprint
- * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
- */
- @Override
- public void finish(boolean strongAuth, int targetUserId) {
- // If there's a pending runnable because the user interacted with a widget
- // and we're leaving keyguard, then run it.
- boolean deferKeyguardDone = false;
- if (mDismissAction != null) {
- deferKeyguardDone = mDismissAction.onDismiss();
- mDismissAction = null;
- mCancelAction = null;
- }
- if (mViewMediatorCallback != null) {
- if (deferKeyguardDone) {
- mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
- } else {
- mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
- }
- }
- }
-
- @Override
- public void reset() {
- mViewMediatorCallback.resetKeyguard();
- }
-
- @Override
- public void onCancelClicked() {
- mViewMediatorCallback.onCancelClicked();
- }
-
- public void resetSecurityContainer() {
- mSecurityContainer.reset();
- }
-
- @Override
- public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.setNeedsInput(needsInput);
- }
- }
-
- public CharSequence getAccessibilityTitleForCurrentMode() {
- return mSecurityContainer.getTitle();
- }
-
- public void userActivity() {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity();
- }
- }
-
- /**
- * Called when the Keyguard is not actively shown anymore on the screen.
- */
- public void onPause() {
- if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
- Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
- mSecurityContainer.showPrimarySecurityScreen(true);
- mSecurityContainer.onPause();
- clearFocus();
- }
-
- /**
- * Called when the Keyguard is actively shown on the screen.
- */
- public void onResume() {
- if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
- mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
- requestFocus();
- }
-
- /**
- * Starts the animation when the Keyguard gets shown.
- */
- public void startAppearAnimation() {
- mSecurityContainer.startAppearAnimation();
- }
-
- public void startDisappearAnimation(Runnable finishRunnable) {
- if (!mSecurityContainer.startDisappearAnimation(finishRunnable) && finishRunnable != null) {
- finishRunnable.run();
- }
- }
-
- /**
- * Called before this view is being removed.
- */
- public void cleanUp() {
- getSecurityContainer().onPause();
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (interceptMediaKey(event)) {
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
-
- /**
- * Allows the media keys to work when the keyguard is showing.
- * The media keys should be of no interest to the actual keyguard view(s),
- * so intercepting them here should not be of any harm.
- * @param event The key event
- * @return whether the event was consumed as a media key.
- */
- public boolean interceptMediaKey(KeyEvent event) {
- final int keyCode = event.getKeyCode();
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- /* Suppress PLAY/PAUSE toggle when phone is ringing or
- * in-call to avoid music playback */
- if (mTelephonyManager == null) {
- mTelephonyManager = (TelephonyManager) getContext().getSystemService(
- Context.TELEPHONY_SERVICE);
- }
- if (mTelephonyManager != null &&
- mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
- return true; // suppress key event
- }
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
- handleMediaKeyEvent(event);
- return true;
- }
-
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_MUTE: {
- if (KEYGUARD_MANAGES_VOLUME) {
- synchronized (this) {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getContext().getSystemService(
- Context.AUDIO_SERVICE);
- }
- }
- // Volume buttons should only function for music (local or remote).
- // TODO: Actually handle MUTE.
- mAudioManager.adjustSuggestedStreamVolume(
- keyCode == KeyEvent.KEYCODE_VOLUME_UP
- ? AudioManager.ADJUST_RAISE
- : AudioManager.ADJUST_LOWER /* direction */,
- AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
- // Don't execute default volume behavior
- return true;
- } else {
- return false;
- }
- }
- }
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
- handleMediaKeyEvent(event);
- return true;
- }
- }
- }
- return false;
- }
-
- private void handleMediaKeyEvent(KeyEvent keyEvent) {
- synchronized (this) {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getContext().getSystemService(
- Context.AUDIO_SERVICE);
- }
- }
- mAudioManager.dispatchMediaKeyEvent(keyEvent);
- }
-
- /**
- * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
- * some cases where we wish to disable it, notably when the menu button placement or technology
- * is prone to false positives.
- *
- * @return true if the menu key should be enabled
- */
- private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
- public boolean shouldEnableMenuKey() {
- final Resources res = getResources();
- final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
- final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
- final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
- return !configDisabled || isTestHarness || fileOverride;
- }
-
public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
mViewMediatorCallback = viewMediatorCallback;
- // Update ViewMediator with the current input method requirements
- mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
- }
-
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- mSecurityContainer.setLockPatternUtils(utils);
- }
-
- public SecurityMode getSecurityMode() {
- return mSecurityContainer.getSecurityMode();
- }
-
- public SecurityMode getCurrentSecurityMode() {
- return mSecurityContainer.getCurrentSecurityMode();
- }
-
- /**
- * When bouncer was visible and is starting to become hidden.
- */
- public void onStartingToHide() {
- mSecurityContainer.onStartingToHide();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
new file mode 100644
index 0000000..7aabb17
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import android.app.ActivityManager;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.os.SystemClock;
+import android.service.trust.TrustAgentService;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnKeyListener;
+import android.view.ViewTreeObserver;
+
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.util.ViewController;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+/** Controller for a {@link KeyguardHostView}. */
+@KeyguardBouncerScope
+public class KeyguardHostViewController extends ViewController<KeyguardHostView> {
+ private static final String TAG = "KeyguardViewBase";
+ public static final boolean DEBUG = KeyguardConstants.DEBUG;
+ // Whether the volume keys should be handled by keyguard. If true, then
+ // they will be handled here for specific media types such as music, otherwise
+ // the audio service will bring up the volume dialog.
+ private static final boolean KEYGUARD_MANAGES_VOLUME = false;
+
+ private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardSecurityContainerController mKeyguardSecurityContainerController;
+ private final TelephonyManager mTelephonyManager;
+ private final ViewMediatorCallback mViewMediatorCallback;
+ private final AudioManager mAudioManager;
+
+ private ActivityStarter.OnDismissAction mDismissAction;
+ private Runnable mCancelAction;
+
+ private final KeyguardUpdateMonitorCallback mUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onUserSwitchComplete(int userId) {
+ mKeyguardSecurityContainerController.showPrimarySecurityScreen(
+ false /* turning off */);
+ }
+
+ @Override
+ public void onTrustGrantedWithFlags(int flags, int userId) {
+ if (userId != KeyguardUpdateMonitor.getCurrentUser()) return;
+ boolean bouncerVisible = mView.isVisibleToUser();
+ boolean initiatedByUser =
+ (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0;
+ boolean dismissKeyguard =
+ (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0;
+
+ if (initiatedByUser || dismissKeyguard) {
+ if (mViewMediatorCallback.isScreenOn()
+ && (bouncerVisible || dismissKeyguard)) {
+ if (!bouncerVisible) {
+ // The trust agent dismissed the keyguard without the user proving
+ // that they are present (by swiping up to show the bouncer). That's
+ // fine if the user proved presence via some other way to the trust
+ //agent.
+ Log.i(TAG, "TrustAgent dismissed Keyguard.");
+ }
+ mSecurityCallback.dismiss(false /* authenticated */, userId,
+ /* bypassSecondaryLockScreen */ false);
+ } else {
+ mViewMediatorCallback.playTrustedSound();
+ }
+ }
+ }
+ };
+
+ private final SecurityCallback mSecurityCallback = new SecurityCallback() {
+
+ @Override
+ public boolean dismiss(boolean authenticated, int targetUserId,
+ boolean bypassSecondaryLockScreen) {
+ return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+ authenticated, targetUserId, bypassSecondaryLockScreen);
+ }
+
+ @Override
+ public void userActivity() {
+ mViewMediatorCallback.userActivity();
+ }
+
+ @Override
+ public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
+ mViewMediatorCallback.setNeedsInput(needsInput);
+ }
+
+ /**
+ * Authentication has happened and it's time to dismiss keyguard. This function
+ * should clean up and inform KeyguardViewMediator.
+ *
+ * @param strongAuth whether the user has authenticated with strong authentication like
+ * pattern, password or PIN but not by trust agents or fingerprint
+ * @param targetUserId a user that needs to be the foreground user at the dismissal
+ * completion.
+ */
+ @Override
+ public void finish(boolean strongAuth, int targetUserId) {
+ // If there's a pending runnable because the user interacted with a widget
+ // and we're leaving keyguard, then run it.
+ boolean deferKeyguardDone = false;
+ if (mDismissAction != null) {
+ deferKeyguardDone = mDismissAction.onDismiss();
+ mDismissAction = null;
+ mCancelAction = null;
+ }
+ if (mViewMediatorCallback != null) {
+ if (deferKeyguardDone) {
+ mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
+ } else {
+ mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
+ }
+ }
+ }
+
+ @Override
+ public void reset() {
+ mViewMediatorCallback.resetKeyguard();
+ }
+
+ @Override
+ public void onCancelClicked() {
+ mViewMediatorCallback.onCancelClicked();
+ }
+ };
+
+ private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
+
+ @Inject
+ public KeyguardHostViewController(KeyguardHostView view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ KeyguardSecurityContainerController keyguardSecurityContainerController,
+ AudioManager audioManager,
+ TelephonyManager telephonyManager,
+ ViewMediatorCallback viewMediatorCallback) {
+ super(view);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardSecurityContainerController = keyguardSecurityContainerController;
+ mAudioManager = audioManager;
+ mTelephonyManager = telephonyManager;
+ mViewMediatorCallback = viewMediatorCallback;
+ }
+
+ /** Initialize the Controller. */
+ public void init() {
+ super.init();
+ mView.setViewMediatorCallback(mViewMediatorCallback);
+ // Update ViewMediator with the current input method requirements
+ mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
+ mKeyguardSecurityContainerController.init();
+ mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback);
+ mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+ mView.setOnKeyListener(mOnKeyListener);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mKeyguardUpdateMonitor.removeCallback(mUpdateCallback);
+ mView.setOnKeyListener(null);
+ }
+
+ /** Called before this view is being removed. */
+ public void cleanUp() {
+ mKeyguardSecurityContainerController.onPause();
+ }
+
+ public void resetSecurityContainer() {
+ mKeyguardSecurityContainerController.reset();
+ }
+
+ /**
+ * Dismisses the keyguard by going to the next screen or making it gone.
+ * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+ * @return True if the keyguard is done.
+ */
+ public boolean dismiss(int targetUserId) {
+ return mSecurityCallback.dismiss(false, targetUserId, false);
+ }
+
+ /**
+ * Called when the Keyguard is actively shown on the screen.
+ */
+ public void onResume() {
+ if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+ mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON);
+ mView.requestFocus();
+ }
+
+ public CharSequence getAccessibilityTitleForCurrentMode() {
+ return mKeyguardSecurityContainerController.getTitle();
+ }
+
+ /**
+ * Starts the animation when the Keyguard gets shown.
+ */
+ public void appear(int statusBarHeight) {
+ // We might still be collapsed and the view didn't have time to layout yet or still
+ // be small, let's wait on the predraw to do the animation in that case.
+ if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) {
+ mKeyguardSecurityContainerController.startAppearAnimation();
+ } else {
+ mView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mView.getViewTreeObserver().removeOnPreDrawListener(this);
+ mKeyguardSecurityContainerController.startAppearAnimation();
+ return true;
+ }
+ });
+ mView.requestLayout();
+ }
+ }
+
+ /**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE},
+ * {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
+ * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
+ * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
+ */
+ public void showPromptReason(int reason) {
+ mKeyguardSecurityContainerController.showPromptReason(reason);
+ }
+
+ public void showMessage(CharSequence message, ColorStateList colorState) {
+ mKeyguardSecurityContainerController.showMessage(message, colorState);
+ }
+
+ public void showErrorMessage(CharSequence customMessage) {
+ showMessage(customMessage, Utils.getColorError(mView.getContext()));
+ }
+
+ /**
+ * Sets an action to run when keyguard finishes.
+ *
+ * @param action
+ */
+ public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
+ if (mCancelAction != null) {
+ mCancelAction.run();
+ mCancelAction = null;
+ }
+ mDismissAction = action;
+ mCancelAction = cancelAction;
+ }
+
+ public void cancelDismissAction() {
+ setOnDismissAction(null, null);
+ }
+
+ public void startDisappearAnimation(Runnable finishRunnable) {
+ if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable)
+ && finishRunnable != null) {
+ finishRunnable.run();
+ }
+ }
+
+ /**
+ * Called when the Keyguard is not actively shown anymore on the screen.
+ */
+ public void onPause() {
+ if (DEBUG) {
+ Log.d(TAG, String.format("screen off, instance %s at %s",
+ Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+ }
+ mKeyguardSecurityContainerController.showPrimarySecurityScreen(true);
+ mKeyguardSecurityContainerController.onPause();
+ mView.clearFocus();
+ }
+
+ /**
+ * Called when the view needs to be shown.
+ */
+ public void showPrimarySecurityScreen() {
+ if (DEBUG) Log.d(TAG, "show()");
+ mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
+ }
+
+ public void setExpansion(float fraction) {
+ float alpha = MathUtils.map(KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
+ mView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
+ mView.setTranslationY(fraction * mView.getHeight());
+ }
+
+ /**
+ * When bouncer was visible and is starting to become hidden.
+ */
+ public void onStartingToHide() {
+ mKeyguardSecurityContainerController.onStartingToHide();
+ }
+
+ public boolean hasDismissActions() {
+ return mDismissAction != null || mCancelAction != null;
+ }
+
+ public SecurityMode getCurrentSecurityMode() {
+ return mKeyguardSecurityContainerController.getCurrentSecurityMode();
+ }
+
+ public int getTop() {
+ int top = mView.getTop();
+ // The password view has an extra top padding that should be ignored.
+ if (getCurrentSecurityMode() == SecurityMode.Password) {
+ View messageArea = mView.findViewById(R.id.keyguard_message_area);
+ top += messageArea.getTop();
+ }
+ return top;
+ }
+
+ public boolean handleBackKey() {
+ if (mKeyguardSecurityContainerController.getCurrentSecuritySelection()
+ != SecurityMode.None) {
+ mKeyguardSecurityContainerController.dismiss(
+ false, KeyguardUpdateMonitor.getCurrentUser());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+ * some cases where we wish to disable it, notably when the menu button placement or technology
+ * is prone to false positives.
+ *
+ * @return true if the menu key should be enabled
+ */
+ public boolean shouldEnableMenuKey() {
+ final Resources res = mView.getResources();
+ final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+ final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+ final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+ return !configDisabled || isTestHarness || fileOverride;
+ }
+
+ /**
+ * Allows the media keys to work when the keyguard is showing.
+ * The media keys should be of no interest to the actual keyguard view(s),
+ * so intercepting them here should not be of any harm.
+ * @param event The key event
+ * @return whether the event was consumed as a media key.
+ */
+ public boolean interceptMediaKey(KeyEvent event) {
+ int keyCode = event.getKeyCode();
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_MEDIA_PLAY:
+ case KeyEvent.KEYCODE_MEDIA_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ /* Suppress PLAY/PAUSE toggle when phone is ringing or
+ * in-call to avoid music playback */
+ if (mTelephonyManager != null &&
+ mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+ return true; // suppress key event
+ }
+ case KeyEvent.KEYCODE_MUTE:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_MEDIA_STOP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ case KeyEvent.KEYCODE_MEDIA_REWIND:
+ case KeyEvent.KEYCODE_MEDIA_RECORD:
+ case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+ case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+ handleMediaKeyEvent(event);
+ return true;
+ }
+
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_MUTE: {
+ if (KEYGUARD_MANAGES_VOLUME) {
+ // Volume buttons should only function for music (local or remote).
+ // TODO: Actually handle MUTE.
+ mAudioManager.adjustSuggestedStreamVolume(
+ keyCode == KeyEvent.KEYCODE_VOLUME_UP
+ ? AudioManager.ADJUST_RAISE
+ : AudioManager.ADJUST_LOWER /* direction */,
+ AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
+ // Don't execute default volume behavior
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_MUTE:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_MEDIA_PLAY:
+ case KeyEvent.KEYCODE_MEDIA_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_STOP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ case KeyEvent.KEYCODE_MEDIA_REWIND:
+ case KeyEvent.KEYCODE_MEDIA_RECORD:
+ case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+ case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+ handleMediaKeyEvent(event);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ private void handleMediaKeyEvent(KeyEvent keyEvent) {
+ mAudioManager.dispatchMediaKeyEvent(keyEvent);
+ }
+
+ public void finish(boolean strongAuth, int currentUser) {
+ mSecurityCallback.finish(strongAuth, currentUser);
+ }
+
+
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
new file mode 100644
index 0000000..f056bdb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+/** Controller for a {@link KeyguardMessageAreaController}. */
+public class KeyguardMessageAreaController extends ViewController<KeyguardMessageArea> {
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final ConfigurationController mConfigurationController;
+
+ private KeyguardMessageAreaController(KeyguardMessageArea view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ ConfigurationController configurationController) {
+ super(view);
+
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mConfigurationController = configurationController;
+ }
+
+ @Override
+ protected void onViewAttached() {
+ //mConfigurationController.addCallback();
+ //mKeyguardUpdateMonitor.registerCallback();
+ }
+
+ @Override
+ protected void onViewDetached() {
+ //mConfigurationController.removeCallback();
+ //mKeyguardUpdateMonitor.removeCallback();
+ }
+
+ /** Factory for createing {@link com.android.keyguard.KeyguardMessageAreaController}. */
+ public static class Factory {
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final ConfigurationController mConfigurationController;
+
+ @Inject
+ public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
+ ConfigurationController configurationController) {
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mConfigurationController = configurationController;
+ }
+
+ /** Build a new {@link KeyguardMessageAreaController}. */
+ public KeyguardMessageAreaController create(KeyguardMessageArea view) {
+ return new KeyguardMessageAreaController(
+ view, mKeyguardUpdateMonitor, mConfigurationController);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
new file mode 100644
index 0000000..5c125fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import android.view.ViewGroup;
+
+import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.keyguard.dagger.RootView;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+/** Controller for a {@link KeyguardBouncer}'s Root view. */
+@KeyguardBouncerScope
+public class KeyguardRootViewController extends ViewController<ViewGroup> {
+ @Inject
+ public KeyguardRootViewController(@RootView ViewGroup view) {
+ super(view);
+ }
+
+ public ViewGroup getView() {
+ return mView;
+ }
+
+ @Override
+ protected void onViewAttached() {
+
+ }
+
+ @Override
+ protected void onViewDetached() {
+
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
new file mode 100644
index 0000000..17f25bd08ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import android.content.res.ColorStateList;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+/** Controller for {@link KeyguardSecurityContainer} */
+public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer> {
+
+ private final LockPatternUtils mLockPatternUtils;
+ private final KeyguardSecurityViewController.Factory mKeyguardSecurityViewControllerFactory;
+
+ @Inject
+ KeyguardSecurityContainerController(KeyguardSecurityContainer view,
+ LockPatternUtils lockPatternUtils,
+ KeyguardSecurityViewController.Factory keyguardSecurityViewControllerFactory) {
+ super(view);
+ mLockPatternUtils = lockPatternUtils;
+ view.setLockPatternUtils(mLockPatternUtils);
+ mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory;
+ }
+
+ @Override
+ protected void onViewAttached() {
+ }
+
+ @Override
+ protected void onViewDetached() {
+ }
+
+ /** */
+ public void onPause() {
+ mView.onPause();
+ }
+
+ public void showPrimarySecurityScreen(boolean turningOff) {
+ mView.showPrimarySecurityScreen(turningOff);
+ }
+
+ public void showPromptReason(int reason) {
+ mView.showPromptReason(reason);
+ }
+
+ public void showMessage(CharSequence message, ColorStateList colorState) {
+ mView.showMessage(message, colorState);
+ }
+
+ public SecurityMode getCurrentSecuritySelection() {
+ return mView.getCurrentSecuritySelection();
+ }
+
+ public void dismiss(boolean authenticated, int targetUserId) {
+ mView.dismiss(authenticated, targetUserId);
+ }
+
+ public void reset() {
+ mView.reset();
+ }
+
+ public CharSequence getTitle() {
+ return mView.getTitle();
+ }
+
+ public void onResume(int screenOn) {
+ mView.onResume(screenOn);
+ }
+
+ public void startAppearAnimation() {
+ mView.startAppearAnimation();
+ }
+
+ public boolean startDisappearAnimation(Runnable onFinishRunnable) {
+ return mView.startDisappearAnimation(onFinishRunnable);
+ }
+
+ public void onStartingToHide() {
+ mView.onStartingToHide();
+ }
+
+ public void setSecurityCallback(SecurityCallback securityCallback) {
+ mView.setSecurityCallback(securityCallback);
+ }
+
+ public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
+ boolean bypassSecondaryLockScreen) {
+ return mView.showNextSecurityScreenOrFinish(
+ authenticated, targetUserId, bypassSecondaryLockScreen);
+ }
+
+ public boolean needsInput() {
+ return mView.needsInput();
+ }
+
+ public SecurityMode getCurrentSecurityMode() {
+ return mView.getCurrentSecurityMode();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java
new file mode 100644
index 0000000..ef9ba19
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 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.keyguard;
+
+import android.view.View;
+
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+
+/** Controller for a {@link KeyguardSecurityView}. */
+public class KeyguardSecurityViewController extends ViewController<View> {
+
+ private final KeyguardSecurityView mView;
+
+ private KeyguardSecurityViewController(KeyguardSecurityView view) {
+ super((View) view);
+ // KeyguardSecurityView isn't actually a View, so we need to track it ourselves.
+ mView = view;
+ }
+
+ @Override
+ protected void onViewAttached() {
+
+ }
+
+ @Override
+ protected void onViewDetached() {
+
+ }
+
+ /** Factory for a {@link KeyguardSecurityViewController}. */
+ public static class Factory {
+ @Inject
+ public Factory() {
+ }
+
+ /** Create a new {@link KeyguardSecurityViewController}. */
+ public KeyguardSecurityViewController create(KeyguardSecurityView view) {
+ return new KeyguardSecurityViewController(view);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1027329..76090f8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.UserSwitchObserver;
@@ -2783,7 +2784,7 @@
@Override
public void onTaskStackChangedBackground() {
try {
- ActivityManager.StackInfo info = ActivityTaskManager.getService().getStackInfo(
+ RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
if (info == null) {
return;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index 84deaca..5160b7e 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -16,27 +16,27 @@
package com.android.keyguard.dagger;
-import android.view.ViewGroup;
-
+import com.android.keyguard.KeyguardHostViewController;
+import com.android.keyguard.KeyguardRootViewController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import dagger.BindsInstance;
import dagger.Subcomponent;
/**
* Dagger Subcomponent for the {@link KeyguardBouncer}.
*/
-@Subcomponent
+@Subcomponent(modules = {KeyguardBouncerModule.class})
@KeyguardBouncerScope
public interface KeyguardBouncerComponent {
/** Simple factory for {@link KeyguardBouncerComponent}. */
@Subcomponent.Factory
interface Factory {
- KeyguardBouncerComponent build(
- @BindsInstance @ContainerView ViewGroup container,
- @BindsInstance KeyguardBouncer.BouncerExpansionCallback bouncerExpansionCallback);
+ KeyguardBouncerComponent create();
}
- /** */
- KeyguardBouncer createKeyguardBouncer();
+ /** Returns a {@link KeyguardRootViewController}. */
+ KeyguardRootViewController getKeyguardRootViewController();
+
+ /** Returns a {@link KeyguardHostViewController}. */
+ KeyguardHostViewController getKeyguardHostViewController();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
new file mode 100644
index 0000000..b6010c8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 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.keyguard.dagger;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardMessageArea;
+import com.android.keyguard.KeyguardSecurityContainer;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Module to create and access view related to the {@link KeyguardBouncer}.
+ */
+@Module
+public interface KeyguardBouncerModule {
+ /** */
+ @Provides
+ @KeyguardBouncerScope
+ @RootView
+ static ViewGroup providesRootView(LayoutInflater layoutInflater) {
+ return (ViewGroup) layoutInflater.inflate(R.layout.keyguard_bouncer, null);
+ }
+
+ /** */
+ @Provides
+ @KeyguardBouncerScope
+ static KeyguardMessageArea providesKeyguardMessageArea(@RootView ViewGroup viewGroup) {
+ return viewGroup.findViewById(R.id.keyguard_message_area);
+ }
+
+ /** */
+ @Provides
+ @KeyguardBouncerScope
+ static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView) {
+ return rootView.findViewById(R.id.keyguard_host_view);
+ }
+
+ /** */
+ @Provides
+ @KeyguardBouncerScope
+ static KeyguardSecurityContainer preovidesKeyguardSecurityContainer(KeyguardHostView hostView) {
+ return hostView.findViewById(R.id.keyguard_security_container);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
similarity index 96%
rename from packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
rename to packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
index e65f19d..5ebff09 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
@@ -26,5 +26,5 @@
@Qualifier
@Documented
@Retention(RUNTIME)
-public @interface ContainerView {
+public @interface RootView {
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index a86a469..9f7358b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -17,9 +17,12 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.PathParser;
import android.widget.ImageView;
@@ -30,6 +33,9 @@
import java.util.EnumSet;
+import static android.graphics.Paint.DITHER_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
/**
* View that displays an adaptive icon with an app-badge and a dot.
*
@@ -43,6 +49,8 @@
public static final float WHITE_SCRIM_ALPHA = 0.54f;
/** Same as value in Launcher3 IconShape */
public static final int DEFAULT_PATH_SIZE = 100;
+ /** Same as value in Launcher3 BaseIconFactory */
+ private static final float ICON_BADGE_SCALE = 0.444f;
/**
* Flags that suppress the visibility of the 'new' dot, for one reason or another. If any of
@@ -69,6 +77,7 @@
private BubbleViewProvider mBubble;
private int mBubbleBitmapSize;
+ private int mBubbleSize;
private DotRenderer mDotRenderer;
private DotRenderer.DrawParams mDrawParams;
private boolean mOnLeft;
@@ -93,6 +102,7 @@
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mBubbleBitmapSize = getResources().getDimensionPixelSize(R.dimen.bubble_bitmap_size);
+ mBubbleSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
mDrawParams = new DotRenderer.DrawParams();
Path iconPath = PathParser.createPathFromPathData(
@@ -108,7 +118,7 @@
*/
public void setRenderedBubble(BubbleViewProvider bubble) {
mBubble = bubble;
- setImageBitmap(bubble.getBadgedImage());
+ showBadge();
mDotColor = bubble.getDotColor();
drawDot(bubble.getDotPath());
}
@@ -161,14 +171,6 @@
}
/**
- * Set whether the dot should appear on left or right side of the view.
- */
- void setDotOnLeft(boolean onLeft) {
- mOnLeft = onLeft;
- invalidate();
- }
-
- /**
* @param iconPath The new icon path to use when calculating dot position.
*/
void drawDot(Path iconPath) {
@@ -219,22 +221,29 @@
return mDotColor;
}
- /** Sets the position of the 'new' dot, animating it out and back in if requested. */
- void setDotPositionOnLeft(boolean onLeft, boolean animate) {
- if (animate && onLeft != getDotOnLeft() && shouldDrawDot()) {
+ /** Sets the position of the dot and badge, animating them out and back in if requested. */
+ void animateDotBadgePositions(boolean onLeft) {
+ mOnLeft = onLeft;
+
+ if (onLeft != getDotOnLeft() && shouldDrawDot()) {
animateDotScale(0f /* showDot */, () -> {
- setDotOnLeft(onLeft);
+ invalidate();
animateDotScale(1.0f, null /* after */);
});
- } else {
- setDotOnLeft(onLeft);
}
+ // TODO animate badge
+ showBadge();
+
}
- boolean getDotPositionOnLeft() {
- return getDotOnLeft();
+ /** Sets the position of the dot and badge. */
+ void setDotBadgeOnLeft(boolean onLeft) {
+ mOnLeft = onLeft;
+ invalidate();
+ showBadge();
}
+
/** Whether to draw the dot in onDraw(). */
private boolean shouldDrawDot() {
// Always render the dot if it's animating, since it could be animating out. Otherwise, show
@@ -276,4 +285,33 @@
}
}).start();
}
+
+ void showBadge() {
+ Drawable badge = mBubble.getAppBadge();
+ if (badge == null) {
+ setImageBitmap(mBubble.getBubbleIcon());
+ return;
+ }
+ Canvas bubbleCanvas = new Canvas();
+ Bitmap noBadgeBubble = mBubble.getBubbleIcon();
+ Bitmap bubble = noBadgeBubble.copy(noBadgeBubble.getConfig(), /* isMutable */ true);
+
+ bubbleCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
+ bubbleCanvas.setBitmap(bubble);
+
+ final int badgeSize = (int) (ICON_BADGE_SCALE * mBubbleSize);
+ if (mOnLeft) {
+ badge.setBounds(0, mBubbleSize - badgeSize, badgeSize, mBubbleSize);
+ } else {
+ badge.setBounds(mBubbleSize - badgeSize, mBubbleSize - badgeSize,
+ mBubbleSize, mBubbleSize);
+ }
+ badge.draw(bubbleCanvas);
+ bubbleCanvas.setBitmap(null);
+ setImageBitmap(bubble);
+ }
+
+ void hideBadge() {
+ setImageBitmap(mBubble.getBubbleIcon());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 62bc425..e6c1bc3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -41,7 +41,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
-import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.io.FileDescriptor;
@@ -92,8 +91,9 @@
}
private FlyoutMessage mFlyoutMessage;
- private Drawable mBadgedAppIcon;
- private Bitmap mBadgedImage;
+ private Drawable mBadgeDrawable;
+ // Bitmap with no badge, no dot
+ private Bitmap mBubbleBitmap;
private int mDotColor;
private Path mDotPath;
private int mFlags;
@@ -199,12 +199,13 @@
}
@Override
- public Bitmap getBadgedImage() {
- return mBadgedImage;
+ public Bitmap getBubbleIcon() {
+ return mBubbleBitmap;
}
- public Drawable getBadgedAppIcon() {
- return mBadgedAppIcon;
+ @Override
+ public Drawable getAppBadge() {
+ return mBadgeDrawable;
}
@Override
@@ -340,8 +341,9 @@
mAppName = info.appName;
mFlyoutMessage = info.flyoutMessage;
- mBadgedAppIcon = info.badgedAppIcon;
- mBadgedImage = info.badgedBubbleImage;
+ mBadgeDrawable = info.badgeDrawable;
+ mBubbleBitmap = info.bubbleBitmap;
+
mDotColor = info.dotColor;
mDotPath = info.dotPath;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
index d017bc0..371e849 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
@@ -156,17 +156,4 @@
canvas.setBitmap(null);
return bitmap;
}
-
- /**
- * Returns a {@link BitmapInfo} for the entire bubble icon including the badge.
- */
- BitmapInfo getBubbleBitmap(Drawable bubble, BitmapInfo badge) {
- BitmapInfo bubbleIconInfo = createBadgedIconBitmap(bubble,
- null /* user */,
- true /* shrinkNonAdaptiveIcons */);
-
- badgeWithDrawable(bubbleIconInfo.icon,
- new BitmapDrawable(mContext.getResources(), badge.icon));
- return bubbleIconInfo;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.kt
index 155b71b..6d3c2a6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.kt
@@ -23,6 +23,7 @@
import android.graphics.Path
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import android.util.PathParser
import android.util.TypedValue
@@ -36,8 +37,9 @@
private val stack: BubbleStackView
) : BubbleViewProvider {
- private var bitmap: Bitmap? = null
- private var dotPath: Path? = null
+ private lateinit var bitmap : Bitmap
+ private lateinit var dotPath : Path
+
private var bitmapSize = 0
private var iconBitmapSize = 0
private var dotColor = 0
@@ -80,40 +82,41 @@
expandedView.updateDimensions()
}
- fun updateBtnTheme() {
+ private fun updateBtnTheme() {
val res = context.resources
// Set overflow button accent color, dot color
val typedValue = TypedValue()
context.theme.resolveAttribute(android.R.attr.colorAccent, typedValue, true)
-
val colorAccent = res.getColor(typedValue.resourceId)
- overflowBtn.getDrawable()?.setTint(colorAccent)
+ overflowBtn.drawable?.setTint(colorAccent)
dotColor = colorAccent
- // Set button and activity background color
- val nightMode = (res.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
- == Configuration.UI_MODE_NIGHT_YES)
- val bg = ColorDrawable(res.getColor(
- if (nightMode) R.color.bubbles_dark else R.color.bubbles_light))
-
- // Set button icon
val iconFactory = BubbleIconFactory(context)
- val fg = InsetDrawable(overflowBtn.getDrawable(),
- bitmapSize - iconBitmapSize /* inset */)
- bitmap = iconFactory.createBadgedIconBitmap(AdaptiveIconDrawable(bg, fg),
- null /* user */, true /* shrinkNonAdaptiveIcons */).icon
- // Set dot path
+ // Update bitmap
+ val nightMode = (res.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
+ == Configuration.UI_MODE_NIGHT_YES)
+ val bg = ColorDrawable(res.getColor(
+ if (nightMode) R.color.bubbles_dark else R.color.bubbles_light))
+
+ val fg = InsetDrawable(overflowBtn.drawable,
+ bitmapSize - iconBitmapSize /* inset */)
+ bitmap = iconFactory.createBadgedIconBitmap(AdaptiveIconDrawable(bg, fg),
+ null /* user */, true /* shrinkNonAdaptiveIcons */).icon
+
+ // Update dot path
dotPath = PathParser.createPathFromPathData(
- res.getString(com.android.internal.R.string.config_icon_mask))
+ res.getString(com.android.internal.R.string.config_icon_mask))
val scale = iconFactory.normalizer.getScale(overflowBtn.getDrawable(),
- null /* outBounds */, null /* path */, null /* outMaskShape */)
+ null /* outBounds */, null /* path */, null /* outMaskShape */)
val radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f
val matrix = Matrix()
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
- radius /* pivot y */)
- dotPath?.transform(matrix)
+ radius /* pivot y */)
+ dotPath.transform(matrix)
+
+ // Attach BubbleOverflow to BadgedImageView
overflowBtn.setRenderedBubble(this)
}
@@ -129,7 +132,11 @@
return dotColor
}
- override fun getBadgedImage(): Bitmap? {
+ override fun getAppBadge(): Drawable? {
+ return null
+ }
+
+ override fun getBubbleIcon(): Bitmap {
return bitmap
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index c1b6882..55f9631 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -16,13 +16,6 @@
package com.android.systemui.bubbles;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_STACK_VIEW;
-import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
-import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -99,6 +92,12 @@
import java.util.List;
import java.util.function.Consumer;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_STACK_VIEW;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
+
/**
* Renders bubbles in a stack and handles animating expanded and collapsed states.
*/
@@ -658,13 +657,10 @@
mStackOnLeftOrWillBe =
mStackAnimationController.flingStackThenSpringToEdge(
viewInitialX + dx, velX, velY) <= 0;
-
- updateBubbleZOrdersAndDotPosition(true /* animate */);
-
+ updateBubbleIcons();
logBubbleEvent(null /* no bubble associated with bubble stack move */,
SysUiStatsLog.BUBBLE_UICHANGED__ACTION__STACK_MOVED);
}
-
mDismissView.hide();
}
@@ -1468,8 +1464,7 @@
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
- bubble.getIconView().setDotPositionOnLeft(
- !mStackOnLeftOrWillBe /* onLeft */, false /* animate */);
+ bubble.getIconView().setDotBadgeOnLeft(!mStackOnLeftOrWillBe /* onLeft */);
bubble.getIconView().setOnClickListener(mBubbleClickListener);
bubble.getIconView().setOnTouchListener(mBubbleTouchListener);
@@ -1520,7 +1515,7 @@
Bubble bubble = bubbles.get(i);
mBubbleContainer.reorderView(bubble.getIconView(), i);
}
- updateBubbleZOrdersAndDotPosition(false /* animate */);
+ updateBubbleIcons();
updatePointerPosition();
}
@@ -2363,7 +2358,7 @@
// name and icon.
if (show && mBubbleData.hasBubbleInStackWithKey(mExpandedBubble.getKey())) {
final Bubble bubble = mBubbleData.getBubbleInStackWithKey(mExpandedBubble.getKey());
- mManageSettingsIcon.setImageDrawable(bubble.getBadgedAppIcon());
+ mManageSettingsIcon.setImageDrawable(bubble.getAppBadge());
mManageSettingsText.setText(getResources().getString(
R.string.bubbles_app_settings, bubble.getAppName()));
}
@@ -2551,28 +2546,31 @@
}
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
- updateBubbleZOrdersAndDotPosition(false);
+ updateBubbleIcons();
}
- /** Sets the appropriate Z-order and dot position for each bubble in the stack. */
- private void updateBubbleZOrdersAndDotPosition(boolean animate) {
+ /**
+ * Sets the appropriate Z-order, badge, and dot position for each bubble in the stack.
+ * Animate dot and badge changes.
+ */
+ private void updateBubbleIcons() {
int bubbleCount = getBubbleCount();
for (int i = 0; i < bubbleCount; i++) {
BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
bv.setZ((mMaxBubbles * mBubbleElevation) - i);
- // If the dot is on the left, and so is the stack, we need to change the dot position.
- if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
- bv.setDotPositionOnLeft(!mStackOnLeftOrWillBe, animate);
- }
-
- if (!mIsExpanded && i > 0) {
- // If we're collapsed and this bubble is behind other bubbles, suppress its dot.
- bv.addDotSuppressionFlag(
- BadgedImageView.SuppressionFlag.BEHIND_STACK);
- } else {
+ if (mIsExpanded) {
bv.removeDotSuppressionFlag(
BadgedImageView.SuppressionFlag.BEHIND_STACK);
+ bv.animateDotBadgePositions(false /* onLeft */);
+ } else if (i == 0) {
+ bv.removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
+ bv.animateDotBadgePositions(!mStackOnLeftOrWillBe);
+ } else {
+ bv.addDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
+ bv.hideBadge();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
index 5749169..28757fa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
@@ -120,8 +120,8 @@
BubbleExpandedView expandedView;
ShortcutInfo shortcutInfo;
String appName;
- Bitmap badgedBubbleImage;
- Drawable badgedAppIcon;
+ Bitmap bubbleBitmap;
+ Drawable badgeDrawable;
int dotColor;
Path dotPath;
Bubble.FlyoutMessage flyoutMessage;
@@ -179,9 +179,10 @@
BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
b.isImportantConversation());
- info.badgedAppIcon = badgedIcon;
- info.badgedBubbleImage = iconFactory.getBubbleBitmap(bubbleDrawable,
- badgeBitmapInfo).icon;
+ info.badgeDrawable = badgedIcon;
+ info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable,
+ null /* user */,
+ true /* shrinkNonAdaptiveIcons */).icon;
// Dot color & placement
Path iconPath = PathParser.createPathFromPathData(
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
index f1a01be..916ad18 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Path;
+import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.annotation.Nullable;
@@ -34,12 +35,17 @@
String getKey();
- Bitmap getBadgedImage();
+ /** Bubble icon bitmap with no badge and no dot. */
+ Bitmap getBubbleIcon();
+
+ /** App badge drawable to draw above bubble icon. */
+ @Nullable Drawable getAppBadge();
+
+ /** Path of normalized bubble icon to draw dot on. */
+ Path getDotPath();
int getDotColor();
- Path getDotPath();
-
boolean showDot();
int getDisplayId();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
index 9dcc3bb..a7d17e1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
@@ -177,7 +177,7 @@
userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT)
}
})
- userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT)
+ userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT, 1f)
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index b464e8ad..89b5c38 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -22,8 +22,8 @@
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -328,14 +328,14 @@
return false;
}
- // Bail early if the pinned stack is staled.
- final ActivityManager.StackInfo pinnedStackInfo;
+ // Bail early if the pinned task is staled.
+ final RootTaskInfo pinnedTaskInfo;
try {
- pinnedStackInfo = ActivityTaskManager.getService()
- .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (pinnedStackInfo == null) return false;
+ pinnedTaskInfo = ActivityTaskManager.getService()
+ .getRootTaskInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ if (pinnedTaskInfo == null) return false;
} catch (RemoteException e) {
- Log.e(TAG, "Failed to get StackInfo for pinned stack", e);
+ Log.e(TAG, "Failed to get RootTaskInfo for pinned task", e);
return false;
}
@@ -362,7 +362,7 @@
getInsetBounds(outInsetBounds);
outBounds.set(postChangeStackBounds);
- t.setBounds(pinnedStackInfo.stackToken, outBounds);
+ t.setBounds(pinnedTaskInfo.token, outBounds);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 5793cdd..a5ee3a0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -99,6 +99,36 @@
private static final int MSG_FINISH_RESIZE = 4;
private static final int MSG_RESIZE_USER = 5;
+ // Not a complete set of states but serves what we want right now.
+ private enum State {
+ UNDEFINED(0),
+ TASK_APPEARED(1),
+ ENTERING_PIP(2),
+ EXITING_PIP(3);
+
+ private final int mStateValue;
+
+ State(int value) {
+ mStateValue = value;
+ }
+
+ private boolean isInPip() {
+ return mStateValue >= TASK_APPEARED.mStateValue
+ && mStateValue != EXITING_PIP.mStateValue;
+ }
+
+ /**
+ * Resize request can be initiated in other component, ignore if we are no longer in PIP,
+ * still waiting for animation or we're exiting from it.
+ *
+ * @return {@code true} if the resize request should be blocked/ignored.
+ */
+ private boolean shouldBlockResizeRequest() {
+ return mStateValue < ENTERING_PIP.mStateValue
+ || mStateValue == EXITING_PIP.mStateValue;
+ }
+ }
+
private final Context mContext;
private final Handler mMainHandler;
private final Handler mUpdateHandler;
@@ -200,8 +230,7 @@
private ActivityManager.RunningTaskInfo mTaskInfo;
private WindowContainerToken mToken;
private SurfaceControl mLeash;
- private boolean mInPip;
- private boolean mExitingPip;
+ private State mState = State.UNDEFINED;
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
@@ -253,11 +282,11 @@
}
public boolean isInPip() {
- return mInPip;
+ return mState.isInPip();
}
public boolean isDeferringEnterPipAnimation() {
- return mInPip && mShouldDeferEnteringPip;
+ return mState.isInPip() && mShouldDeferEnteringPip;
}
/**
@@ -286,9 +315,9 @@
* @param animationDurationMs duration in millisecond for the exiting PiP transition
*/
public void exitPip(int animationDurationMs) {
- if (!mInPip || mExitingPip || mToken == null) {
+ if (!mState.isInPip() || mState == State.EXITING_PIP || mToken == null) {
Log.wtf(TAG, "Not allowed to exitPip in current state"
- + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken);
+ + " mState=" + mState + " mToken=" + mToken);
return;
}
@@ -303,6 +332,7 @@
? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_LEAVE_PIP;
if (orientationDiffers) {
+ mState = State.EXITING_PIP;
// Send started callback though animation is ignored.
sendOnPipTransitionStarted(direction);
// Don't bother doing an animation if the display rotation differs or if it's in
@@ -311,7 +341,6 @@
mTaskOrganizer.applyTransaction(wct);
// Send finished callback though animation is ignored.
sendOnPipTransitionFinished(direction);
- mInPip = false;
} else {
final SurfaceControl.Transaction tx =
mSurfaceControlTransactionFactory.getTransaction();
@@ -333,11 +362,10 @@
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
null /* sourceHintRect */, direction, animationDurationMs,
null /* updateBoundsCallback */);
- mInPip = false;
+ mState = State.EXITING_PIP;
}
});
}
- mExitingPip = true;
}
private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) {
@@ -356,9 +384,9 @@
* Removes PiP immediately.
*/
public void removePip() {
- if (!mInPip || mExitingPip || mToken == null) {
+ if (!mState.isInPip() || mToken == null) {
Log.wtf(TAG, "Not allowed to removePip in current state"
- + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken);
+ + " mState=" + mState + " mToken=" + mToken);
return;
}
@@ -370,7 +398,7 @@
.setDuration(mEnterExitAnimationDuration)
.start());
mInitialState.remove(mToken.asBinder());
- mExitingPip = true;
+ mState = State.EXITING_PIP;
}
private void removePipImmediately() {
@@ -392,8 +420,7 @@
Objects.requireNonNull(info, "Requires RunningTaskInfo");
mTaskInfo = info;
mToken = mTaskInfo.token;
- mInPip = true;
- mExitingPip = false;
+ mState = State.TASK_APPEARED;
mLeash = leash;
mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
@@ -423,6 +450,7 @@
scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */);
+ mState = State.ENTERING_PIP;
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
enterPipWithAlphaAnimation(destinationBounds, mEnterExitAnimationDuration);
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
@@ -468,6 +496,9 @@
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
.start());
+ // mState is set right after the animation is kicked off to block any resize
+ // requests such as offsetPip that may have been called prior to the transition.
+ mState = State.ENTERING_PIP;
}
});
}
@@ -560,7 +591,7 @@
*/
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
- if (!mInPip) {
+ if (!mState.isInPip()) {
return;
}
final WindowContainerToken token = info.token;
@@ -571,8 +602,7 @@
}
mShouldDeferEnteringPip = false;
mPictureInPictureParams = null;
- mInPip = false;
- mExitingPip = false;
+ mState = State.UNDEFINED;
mPipUiEventLoggerLogger.setTaskInfo(null);
}
@@ -600,7 +630,7 @@
@Override
public void onFixedRotationFinished(int displayId) {
- if (mShouldDeferEnteringPip && mInPip) {
+ if (mShouldDeferEnteringPip && mState.isInPip()) {
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
@@ -623,7 +653,7 @@
mPipAnimationController.getCurrentAnimator();
if (animator == null || !animator.isRunning()
|| animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
- if (mInPip && fromRotation) {
+ if (mState.isInPip() && fromRotation) {
// If we are rotating while there is a current animation, immediately cancel the
// animation (remove the listeners so we don't trigger the normal finish resize
// call that should only happen on the update thread)
@@ -712,10 +742,10 @@
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
int durationMs, Consumer<Rect> updateBoundsCallback) {
- if (!mInPip) {
+ if (!mState.isInPip()) {
// TODO: tend to use shouldBlockResizeRequest here as well but need to consider
// the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
- // container transaction callback and we want to set the mExitingPip immediately.
+ // container transaction callback and we want to set the mState immediately.
return;
}
@@ -772,7 +802,7 @@
private void scheduleFinishResizePip(Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction,
Consumer<Rect> updateBoundsCallback) {
- if (shouldBlockResizeRequest()) {
+ if (mState.shouldBlockResizeRequest()) {
return;
}
@@ -791,7 +821,7 @@
mSurfaceTransactionHelper
.crop(tx, mLeash, destinationBounds)
.resetScale(tx, mLeash, destinationBounds)
- .round(tx, mLeash, mInPip);
+ .round(tx, mLeash, mState.isInPip());
return tx;
}
@@ -800,7 +830,7 @@
*/
public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
Consumer<Rect> updateBoundsCallback) {
- if (shouldBlockResizeRequest()) {
+ if (mState.shouldBlockResizeRequest()) {
return;
}
if (mShouldDeferEnteringPip) {
@@ -845,7 +875,7 @@
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper
.crop(tx, mLeash, destinationBounds)
- .round(tx, mLeash, mInPip);
+ .round(tx, mLeash, mState.isInPip());
tx.apply();
}
@@ -983,16 +1013,6 @@
}
/**
- * Resize request can be initiated in other component, ignore if we are no longer in PIP
- * or we're exiting from it.
- *
- * @return {@code true} if the resize request should be blocked/ignored.
- */
- private boolean shouldBlockResizeRequest() {
- return !mInPip || mExitingPip;
- }
-
- /**
* Sync with {@link SplitScreen} on destination bounds if PiP is going to split screen.
*
* @param destinationBoundsOut contain the updated destination bounds if applicable
@@ -1026,7 +1046,7 @@
pw.println(innerPrefix + "mToken=" + mToken
+ " binder=" + (mToken != null ? mToken.asBinder() : null));
pw.println(innerPrefix + "mLeash=" + mLeash);
- pw.println(innerPrefix + "mInPip=" + mInPip);
+ pw.println(innerPrefix + "mState=" + mState);
pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
index 6998e90..4f225e2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
@@ -25,6 +25,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityManager;
import android.app.RemoteAction;
import android.content.ComponentName;
@@ -324,9 +325,9 @@
configController.addCallback(mOverlayChangedListener);
try {
- ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo(
+ RootTaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (stackInfo != null) {
+ if (taskInfo != null) {
// If SystemUI restart, and it already existed a pinned stack,
// register the pip input consumer to ensure touch can send to it.
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 873ba26..d308172 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -19,8 +19,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.RemoteAction;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -312,10 +312,10 @@
// Fetch the pinned stack bounds
Rect stackBounds = null;
try {
- StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
+ RootTaskInfo pinnedTaskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (pinnedStackInfo != null) {
- stackBounds = pinnedStackInfo.bounds;
+ if (pinnedTaskInfo != null) {
+ stackBounds = pinnedTaskInfo.bounds;
}
} catch (RemoteException e) {
Log.e(TAG, "Error showing PIP menu", e);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
index 993bfe0..c66f442 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
@@ -475,12 +475,10 @@
final Pair<ComponentName, Integer> topPipActivityInfo =
PipUtils.getTopPipActivity(mContext, ActivityManager.getService());
if (topPipActivityInfo.first != null) {
- final UserHandle user = UserHandle.of(topPipActivityInfo.second);
final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS,
Uri.fromParts("package", topPipActivityInfo.first.getPackageName(), null));
- settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user);
settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivity(settingsIntent);
+ mContext.startActivityAsUser(settingsIntent, UserHandle.CURRENT);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index 50d20d3..08d9b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -15,7 +15,7 @@
*/
package com.android.systemui.pip.phone;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_USER_RESIZE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_PINCH_RESIZE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
@@ -46,6 +46,7 @@
import android.view.InputEventReceiver;
import android.view.InputMonitor;
import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import com.android.internal.policy.TaskResizingAlgorithm;
@@ -67,6 +68,8 @@
public class PipResizeGestureHandler {
private static final String TAG = "PipResizeGestureHandler";
+ private static final float PINCH_THRESHOLD = 0.05f;
+ private static final float STARTING_SCALE_FACTOR = 1.0f;
private static final int INVALID_SYSUI_STATE_MASK =
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
@@ -83,6 +86,7 @@
private final int mDisplayId;
private final Executor mMainExecutor;
private final SysUiState mSysUiState;
+ private final ScaleGestureDetector mScaleGestureDetector;
private final Region mTmpRegion = new Region();
private final PointF mDownPoint = new PointF();
@@ -105,8 +109,10 @@
private boolean mAllowGesture;
private boolean mIsAttached;
private boolean mIsEnabled;
- private boolean mEnableUserResize;
+ private boolean mEnablePinchResize;
private boolean mThresholdCrossed;
+ private boolean mUsingPinchToZoom = false;
+ private float mScaleFactor = STARTING_SCALE_FACTOR;
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
@@ -136,17 +142,73 @@
context.getDisplay().getRealSize(mMaxSize);
reloadResources();
- mEnableUserResize = DeviceConfig.getBoolean(
+ mScaleGestureDetector = new ScaleGestureDetector(context,
+ new ScaleGestureDetector.OnScaleGestureListener() {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ mScaleFactor *= detector.getScaleFactor();
+
+ if (!mThresholdCrossed
+ && (mScaleFactor > (STARTING_SCALE_FACTOR + PINCH_THRESHOLD)
+ || mScaleFactor < (STARTING_SCALE_FACTOR - PINCH_THRESHOLD))) {
+ mThresholdCrossed = true;
+ mInputMonitor.pilferPointers();
+ }
+ if (mThresholdCrossed) {
+ int height = Math.min(mMaxSize.y, Math.max(mMinSize.y,
+ (int) (mScaleFactor * mLastDownBounds.height())));
+ int width = Math.min(mMaxSize.x, Math.max(mMinSize.x,
+ (int) (mScaleFactor * mLastDownBounds.width())));
+ int top, bottom, left, right;
+
+ if ((mCtrlType & CTRL_TOP) != 0) {
+ top = mLastDownBounds.bottom - height;
+ bottom = mLastDownBounds.bottom;
+ } else {
+ top = mLastDownBounds.top;
+ bottom = mLastDownBounds.top + height;
+ }
+
+ if ((mCtrlType & CTRL_LEFT) != 0) {
+ left = mLastDownBounds.right - width;
+ right = mLastDownBounds.right;
+ } else {
+ left = mLastDownBounds.left;
+ right = mLastDownBounds.left + width;
+ }
+
+ mLastResizeBounds.set(left, top, right, bottom);
+ mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds,
+ mLastResizeBounds,
+ null);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ setCtrlTypeForPinchToZoom();
+ return true;
+ }
+
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ mScaleFactor = STARTING_SCALE_FACTOR;
+ finishResize();
+ }
+ });
+
+ mEnablePinchResize = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
- PIP_USER_RESIZE,
- /* defaultValue = */ true);
+ PIP_PINCH_RESIZE,
+ /* defaultValue = */ false);
deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor,
new DeviceConfig.OnPropertiesChangedListener() {
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
- if (properties.getKeyset().contains(PIP_USER_RESIZE)) {
- mEnableUserResize = properties.getBoolean(
- PIP_USER_RESIZE, /* defaultValue = */ true);
+ if (properties.getKeyset().contains(PIP_PINCH_RESIZE)) {
+ mEnablePinchResize = properties.getBoolean(
+ PIP_PINCH_RESIZE, /* defaultValue = */ false);
}
}
});
@@ -193,7 +255,7 @@
}
private void updateIsEnabled() {
- boolean isEnabled = mIsAttached && mEnableUserResize;
+ boolean isEnabled = mIsAttached;
if (isEnabled == mIsEnabled) {
return;
}
@@ -211,7 +273,11 @@
private void onInputEvent(InputEvent ev) {
if (ev instanceof MotionEvent) {
- onMotionEvent((MotionEvent) ev);
+ if (mUsingPinchToZoom) {
+ mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
+ } else {
+ onDragCornerResize((MotionEvent) ev);
+ }
}
}
@@ -254,8 +320,51 @@
}
public boolean willStartResizeGesture(MotionEvent ev) {
- return mEnableUserResize && isInValidSysUiState()
- && isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY());
+ if (isInValidSysUiState()) {
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // Always pass the DOWN event to the ScaleGestureDetector
+ mScaleGestureDetector.onTouchEvent(ev);
+ if (isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY())) {
+ return true;
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mEnablePinchResize && ev.getPointerCount() == 2) {
+ mUsingPinchToZoom = true;
+ return true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ private void setCtrlTypeForPinchToZoom() {
+ final Rect currentPipBounds = mMotionHelper.getBounds();
+ mLastDownBounds.set(mMotionHelper.getBounds());
+
+ Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds);
+ mDisplayBounds.set(movementBounds.left,
+ movementBounds.top,
+ movementBounds.right + currentPipBounds.width(),
+ movementBounds.bottom + currentPipBounds.height());
+
+ if (currentPipBounds.left == mDisplayBounds.left) {
+ mCtrlType |= CTRL_RIGHT;
+ } else {
+ mCtrlType |= CTRL_LEFT;
+ }
+
+ if (currentPipBounds.top > mDisplayBounds.top + mDisplayBounds.height()) {
+ mCtrlType |= CTRL_TOP;
+ } else {
+ mCtrlType |= CTRL_BOTTOM;
+ }
}
private void setCtrlType(int x, int y) {
@@ -295,7 +404,7 @@
return (mSysUiState.getFlags() & INVALID_SYSUI_STATE_MASK) == 0;
}
- private void onMotionEvent(MotionEvent ev) {
+ private void onDragCornerResize(MotionEvent ev) {
int action = ev.getActionMasked();
float x = ev.getX();
float y = ev.getY();
@@ -345,28 +454,33 @@
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (!mLastResizeBounds.isEmpty()) {
- mUserResizeBounds.set(mLastResizeBounds);
- mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
- (Rect bounds) -> {
- new Handler(Looper.getMainLooper()).post(() -> {
- mMotionHelper.synchronizePinnedStackBounds();
- mUpdateMovementBoundsRunnable.run();
- resetState();
- });
- });
- mPipUiEventLogger.log(
- PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
- } else {
- resetState();
- }
+ finishResize();
break;
}
}
}
+ private void finishResize() {
+ if (!mLastResizeBounds.isEmpty()) {
+ mUserResizeBounds.set(mLastResizeBounds);
+ mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
+ (Rect bounds) -> {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ mMotionHelper.synchronizePinnedStackBounds();
+ mUpdateMovementBoundsRunnable.run();
+ resetState();
+ });
+ });
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
+ } else {
+ resetState();
+ }
+ }
+
private void resetState() {
mCtrlType = CTRL_NONE;
+ mUsingPinchToZoom = false;
mAllowGesture = false;
mThresholdCrossed = false;
}
@@ -397,7 +511,7 @@
pw.println(innerPrefix + "mAllowGesture=" + mAllowGesture);
pw.println(innerPrefix + "mIsAttached=" + mIsAttached);
pw.println(innerPrefix + "mIsEnabled=" + mIsEnabled);
- pw.println(innerPrefix + "mEnableUserResize=" + mEnableUserResize);
+ pw.println(innerPrefix + "mEnablePinchResize=" + mEnablePinchResize);
pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 9693f23..97b3484 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -650,8 +650,7 @@
}
MotionEvent ev = (MotionEvent) inputEvent;
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN
- && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
+ if (mPipResizeGestureHandler.willStartResizeGesture(ev)) {
// Initialize the touch state for the gesture, but immediately reset to invalidate the
// gesture
mTouchState.onTouchEvent(ev);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
index 4cfec01..baa8f11 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
@@ -19,8 +19,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -40,15 +40,15 @@
IActivityManager activityManager) {
try {
final String sysUiPackageName = context.getPackageName();
- final StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
+ final RootTaskInfo pinnedTaskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
- pinnedStackInfo.taskIds.length > 0) {
- for (int i = pinnedStackInfo.taskNames.length - 1; i >= 0; i--) {
+ if (pinnedTaskInfo != null && pinnedTaskInfo.childTaskIds != null
+ && pinnedTaskInfo.childTaskIds.length > 0) {
+ for (int i = pinnedTaskInfo.childTaskNames.length - 1; i >= 0; i--) {
ComponentName cn = ComponentName.unflattenFromString(
- pinnedStackInfo.taskNames[i]);
+ pinnedTaskInfo.childTaskNames[i]);
if (cn != null && !cn.getPackageName().equals(sysUiPackageName)) {
- return new Pair<>(cn, pinnedStackInfo.taskUserIds[i]);
+ return new Pair<>(cn, pinnedTaskInfo.childTaskUserIds[i]);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java
index 3b3235f..12a545a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java
@@ -21,8 +21,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.app.RemoteAction;
import android.content.BroadcastReceiver;
@@ -289,7 +289,7 @@
// 1. Configuration changed due to the language change (RTL <-> RTL)
// 2. SystemUI restarts after the crash
mPipBounds = mDefaultPipBounds;
- resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP);
+ resizePinnedStack(getPinnedTaskInfo() == null ? STATE_NO_PIP : STATE_PIP);
}
/**
@@ -505,15 +505,15 @@
return mState != STATE_NO_PIP;
}
- private StackInfo getPinnedStackInfo() {
- StackInfo stackInfo = null;
+ private RootTaskInfo getPinnedTaskInfo() {
+ RootTaskInfo taskInfo = null;
try {
- stackInfo = ActivityTaskManager.getService().getStackInfo(
+ taskInfo = ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
} catch (RemoteException e) {
- Log.e(TAG, "getStackInfo failed", e);
+ Log.e(TAG, "getRootTaskInfo failed", e);
}
- return stackInfo;
+ return taskInfo;
}
private void handleMediaResourceGranted(String[] packageNames) {
@@ -611,14 +611,14 @@
if (getState() != STATE_NO_PIP) {
boolean hasPip = false;
- StackInfo stackInfo = getPinnedStackInfo();
- if (stackInfo == null || stackInfo.taskIds == null) {
+ RootTaskInfo taskInfo = getPinnedTaskInfo();
+ if (taskInfo == null || taskInfo.childTaskIds == null) {
Log.w(TAG, "There is nothing in pinned stack");
closePipInternal(false);
return;
}
- for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
- if (stackInfo.taskIds[i] == mPipTaskId) {
+ for (int i = taskInfo.childTaskIds.length - 1; i >= 0; --i) {
+ if (taskInfo.childTaskIds[i] == mPipTaskId) {
// PIP task is still alive.
hasPip = true;
break;
@@ -642,16 +642,16 @@
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
- StackInfo stackInfo = getPinnedStackInfo();
- if (stackInfo == null) {
+ RootTaskInfo taskInfo = getPinnedTaskInfo();
+ if (taskInfo == null) {
Log.w(TAG, "Cannot find pinned stack");
return;
}
- if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
- mPinnedStackId = stackInfo.stackId;
- mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
+ if (DEBUG) Log.d(TAG, "PINNED_STACK:" + taskInfo);
+ mPinnedStackId = taskInfo.taskId;
+ mPipTaskId = taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1];
mPipComponentName = ComponentName.unflattenFromString(
- stackInfo.taskNames[stackInfo.taskNames.length - 1]);
+ taskInfo.childTaskNames[taskInfo.childTaskNames.length - 1]);
// Set state to STATE_PIP so we show it when the pinned stack animation ends.
mState = STATE_PIP;
mMediaSessionManager.addOnActiveSessionsChangedListener(
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 4d6d71c..0fbd73b 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -86,9 +86,9 @@
ALL_INDICATORS, DEFAULT_ALL_INDICATORS)
}
+ // TODO(b/168209929) Remove hardcode
private fun isMicCameraEnabled(): Boolean {
- return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- MIC_CAMERA, DEFAULT_MIC_CAMERA)
+ return true
}
private var currentUserIds = emptyList<Int>()
@@ -124,11 +124,11 @@
DEFAULT_ALL_INDICATORS)
callbacks.forEach { it.get()?.onFlagAllChanged(allIndicatorsAvailable) }
}
-
- if (properties.keyset.contains(MIC_CAMERA)) {
- micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA)
- callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
- }
+ // TODO(b/168209929) Uncomment
+// if (properties.keyset.contains(MIC_CAMERA)) {
+// micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA)
+// callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
+// }
internalUiExecutor.updateListeningState()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index cba938f..2a976f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -75,8 +75,6 @@
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.onehanded.OneHanded;
-import com.android.systemui.onehanded.OneHandedEvents;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -93,6 +91,8 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedEvents;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 7dd4edd..2b4fa2a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -574,7 +574,8 @@
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
if (mScreenshotLayout.isAttachedToWindow()) {
- if (!mDismissAnimation.isRunning()) { // if we didn't already dismiss for another reason
+ // if we didn't already dismiss for another reason
+ if (mDismissAnimation == null || !mDismissAnimation.isRunning()) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
}
dismissScreenshot("new screenshot requested", true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 9586795..a816ecc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -516,6 +516,7 @@
return mLifetimeExtenders;
}
+ @Nullable
public RemoteInputController getController() {
return mRemoteInputController;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 6f7b32b..363a085 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -26,6 +26,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
@@ -161,16 +162,16 @@
() -> {
ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
try {
- final ActivityManager.StackInfo focusedStack =
- ActivityTaskManager.getService().getFocusedStackInfo();
- if (focusedStack != null) {
+ final RootTaskInfo focusedTask =
+ ActivityTaskManager.getService().getFocusedRootTaskInfo();
+ if (focusedTask != null) {
final int windowingMode =
- focusedStack.configuration.windowConfiguration
+ focusedTask.configuration.windowConfiguration
.getWindowingMode();
if (windowingMode == WINDOWING_MODE_FULLSCREEN
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
|| windowingMode == WINDOWING_MODE_FREEFORM) {
- checkAndPostForStack(focusedStack, notifs, noMan, pm);
+ checkAndPostForStack(focusedTask, notifs, noMan, pm);
}
}
if (mDockedStackExists) {
@@ -205,10 +206,8 @@
@NonNull NotificationManager noMan,
@NonNull IPackageManager pm) {
try {
- final ActivityManager.StackInfo info =
- ActivityTaskManager.getService()
- .getStackInfo(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ final RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
checkAndPostForStack(info, notifs, noMan, pm);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
@@ -221,7 +220,7 @@
* exists, this method removes it from {@code notifs} in the arguments.
*/
private void checkAndPostForStack(
- @Nullable ActivityManager.StackInfo info,
+ @Nullable RootTaskInfo info,
@NonNull ArraySet<Pair<String, Integer>> notifs,
@NonNull NotificationManager noMan,
@NonNull IPackageManager pm) {
@@ -241,7 +240,7 @@
info.userId,
appInfo,
noMan,
- info.taskIds[info.taskIds.length - 1]);
+ info.childTaskIds[info.childTaskIds.length - 1]);
}
}
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index 82c1f24..fd0476b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -110,4 +110,11 @@
mPreviousAttachState.clone(mAttachState);
mAttachState.reset();
}
+
+ /**
+ * True if this entry was attached in the last pass, else false.
+ */
+ public boolean wasAttachedInPreviousPass() {
+ return getPreviousAttachState().getParent() != null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 2b545c5..a0ef1b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -513,28 +513,66 @@
}
}
- private void stabilizeGroupingNotifs(List<ListEntry> list) {
+ private void stabilizeGroupingNotifs(List<ListEntry> topLevelList) {
if (mNotifStabilityManager == null) {
return;
}
- for (int i = 0; i < list.size(); i++) {
- final ListEntry tle = list.get(i);
- if (tle.getPreviousAttachState().getParent() == null) {
- continue; // new entries are allowed
- }
-
- final GroupEntry prevParent = tle.getPreviousAttachState().getParent();
- final GroupEntry assignedParent = tle.getParent();
- if (prevParent != assignedParent) {
- if (!mNotifStabilityManager.isGroupChangeAllowed(tle.getRepresentativeEntry())) {
- tle.getAttachState().getSuppressedChanges().setParent(assignedParent);
- tle.setParent(prevParent);
+ for (int i = 0; i < topLevelList.size(); i++) {
+ final ListEntry tle = topLevelList.get(i);
+ if (tle instanceof GroupEntry) {
+ // maybe put children back into their old group (including moving back to top-level)
+ GroupEntry groupEntry = (GroupEntry) tle;
+ List<NotificationEntry> children = groupEntry.getRawChildren();
+ for (int j = 0; j < groupEntry.getChildren().size(); j++) {
+ if (maybeSuppressGroupChange(children.get(j), topLevelList)) {
+ // child was put back into its previous group, so we remove it from this
+ // group
+ children.remove(j);
+ j--;
+ }
+ }
+ } else {
+ // maybe put top-level-entries back into their previous groups
+ if (maybeSuppressGroupChange(tle.getRepresentativeEntry(), topLevelList)) {
+ // entry was put back into its previous group, so we remove it from the list of
+ // top-level-entries
+ topLevelList.remove(i);
+ i--;
}
}
}
}
+ /**
+ * Returns true if the group change was suppressed, else false
+ */
+ private boolean maybeSuppressGroupChange(NotificationEntry entry, List<ListEntry> out) {
+ if (!entry.wasAttachedInPreviousPass()) {
+ return false; // new entries are allowed
+ }
+
+ final GroupEntry prevParent = entry.getPreviousAttachState().getParent();
+ final GroupEntry assignedParent = entry.getParent();
+ if (prevParent != assignedParent
+ && !mNotifStabilityManager.isGroupChangeAllowed(entry.getRepresentativeEntry())) {
+ entry.getAttachState().getSuppressedChanges().setParent(assignedParent);
+ entry.setParent(prevParent);
+ if (prevParent == ROOT_ENTRY) {
+ out.add(entry);
+ } else if (prevParent != null) {
+ prevParent.addChild(entry);
+ if (!mGroups.containsKey(prevParent.getKey())) {
+ mGroups.put(prevParent.getKey(), prevParent);
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
private void promoteNotifs(List<ListEntry> list) {
for (int i = 0; i < list.size(); i++) {
final ListEntry tle = list.get(i);
@@ -577,6 +615,17 @@
} else if (group.getSummary() == null
|| children.size() < MIN_CHILDREN_FOR_GROUP) {
+
+ if (group.getSummary() != null
+ && group.wasAttachedInPreviousPass()
+ && mNotifStabilityManager != null
+ && !mNotifStabilityManager.isGroupChangeAllowed(group.getSummary())) {
+ // if this group was previously attached and group changes aren't
+ // allowed, keep it around until group changes are allowed again
+ group.getAttachState().getSuppressedChanges().setWasPruneSuppressed(true);
+ continue;
+ }
+
// If the group doesn't provide a summary or is too small, ignore it and add
// its children (if any) directly to top-level.
@@ -673,7 +722,6 @@
GroupEntry parent = (GroupEntry) entry;
for (NotificationEntry child : parent.getChildren()) {
child.getAttachState().setSection(section);
- child.getAttachState().setSection(section);
}
parent.sortChildren(sChildComparator);
}
@@ -719,6 +767,12 @@
curr.getParent());
}
+ if (curr.getSuppressedChanges().getWasPruneSuppressed()) {
+ mLogger.logGroupPruningSuppressed(
+ mIterationCount,
+ curr.getParent());
+ }
+
if (curr.getExcludingFilter() != prev.getExcludingFilter()) {
mLogger.logFilterChanged(
mIterationCount,
@@ -868,9 +922,9 @@
NotifSection finalSection = newSection;
- // are we changing sections of this entry?
+ // have we seen this entry before and are we changing its section?
if (mNotifStabilityManager != null
- && prevAttachState.getParent() != null
+ && entry.wasAttachedInPreviousPass()
&& newSection != prevAttachState.getSection()) {
// are section changes allowed?
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
index 3eb2e61..584563b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
@@ -24,28 +24,37 @@
*/
data class SuppressedAttachState private constructor(
/**
- * Null if not attached to the current shade list. If top-level, then the shade list root. If
- * part of a group, then that group's GroupEntry.
+ * The suppressed section assignment for this ListEntry.
+ * Null if no section change was suppressed.
+ */
+ var section: NotifSection?,
+
+ /**
+ * The suppressed parent assignment for this ListEntry.
+ * - Null if no parent change was suppressed.
+ * - Root if suppressing group change to top-level
+ * - GroupEntry if suppressing group change to a different group
*/
var parent: GroupEntry?,
/**
- * The assigned section for this ListEntry. If the child of the group, this will be the
- * parent's section. Null if not attached to the list.
+ * Whether the ListEntry would have been pruned had its group change not been suppressed.
*/
- var section: NotifSection?
+ var wasPruneSuppressed: Boolean
) {
/** Copies the state of another instance. */
fun clone(other: SuppressedAttachState) {
parent = other.parent
section = other.section
+ wasPruneSuppressed = other.wasPruneSuppressed
}
/** Resets back to a "clean" state (the same as created by the factory method) */
fun reset() {
parent = null
section = null
+ wasPruneSuppressed = false
}
companion object {
@@ -53,7 +62,8 @@
fun create(): SuppressedAttachState {
return SuppressedAttachState(
null,
- null)
+ null,
+ false)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index 3aaa9ac..f0eb084 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -22,6 +22,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.render.NodeController
+import com.android.systemui.statusbar.notification.dagger.PeopleHeader
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import javax.inject.Inject
@@ -33,7 +35,8 @@
*/
@SysUISingleton
class ConversationCoordinator @Inject constructor(
- private val peopleNotificationIdentifier: PeopleNotificationIdentifier
+ private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
+ @PeopleHeader peopleHeaderController: NodeController
) : Coordinator {
private val notificationPromoter = object : NotifPromoter(TAG) {
@@ -43,9 +46,9 @@
}
val sectioner = object : NotifSectioner("People") {
- override fun isInSection(entry: ListEntry): Boolean {
- return isConversation(entry.representativeEntry!!)
- }
+ override fun isInSection(entry: ListEntry): Boolean =
+ isConversation(entry.representativeEntry!!)
+ override fun getHeaderNodeController() = peopleHeaderController
}
override fun attach(pipeline: NotifPipeline) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index 24e912e..be1383f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -30,6 +30,8 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.dagger.IncomingHeader;
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -61,6 +63,7 @@
private final HeadsUpViewBinder mHeadsUpViewBinder;
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final NotificationRemoteInputManager mRemoteInputManager;
+ private final NodeController mIncomingHeaderController;
// tracks the current HeadUpNotification reported by HeadsUpManager
private @Nullable NotificationEntry mCurrentHun;
@@ -73,11 +76,13 @@
HeadsUpManager headsUpManager,
HeadsUpViewBinder headsUpViewBinder,
NotificationInterruptStateProvider notificationInterruptStateProvider,
- NotificationRemoteInputManager remoteInputManager) {
+ NotificationRemoteInputManager remoteInputManager,
+ @IncomingHeader NodeController incomingHeaderController) {
mHeadsUpManager = headsUpManager;
mHeadsUpViewBinder = headsUpViewBinder;
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mRemoteInputManager = remoteInputManager;
+ mIncomingHeaderController = incomingHeaderController;
}
@Override
@@ -196,6 +201,12 @@
public boolean isInSection(ListEntry entry) {
return isCurrentlyShowingHun(entry);
}
+
+ @Nullable
+ @Override
+ public NodeController getHeaderNodeController() {
+ return mIncomingHeaderController;
+ }
};
private final OnHeadsUpChangedListener mOnHeadsUpChangedListener =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 0f08e0f..133ddfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import android.annotation.Nullable;
+
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -24,6 +26,9 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
+import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import javax.inject.Inject;
@@ -40,13 +45,19 @@
private final StatusBarStateController mStatusBarStateController;
private final HighPriorityProvider mHighPriorityProvider;
+ private final NodeController mSilentHeaderController;
+ private final NodeController mAlertingHeaderController;
@Inject
public RankingCoordinator(
StatusBarStateController statusBarStateController,
- HighPriorityProvider highPriorityProvider) {
+ HighPriorityProvider highPriorityProvider,
+ @AlertingHeader NodeController alertingHeaderController,
+ @SilentHeader NodeController silentHeaderController) {
mStatusBarStateController = statusBarStateController;
mHighPriorityProvider = highPriorityProvider;
+ mAlertingHeaderController = alertingHeaderController;
+ mSilentHeaderController = silentHeaderController;
}
@Override
@@ -70,6 +81,12 @@
public boolean isInSection(ListEntry entry) {
return mHighPriorityProvider.isHighPriority(entry);
}
+
+ @Nullable
+ @Override
+ public NodeController getHeaderNodeController() {
+ return mAlertingHeaderController;
+ }
};
private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent") {
@@ -77,6 +94,12 @@
public boolean isInSection(ListEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry);
}
+
+ @Nullable
+ @Override
+ public NodeController getHeaderNodeController() {
+ return mSilentHeaderController;
+ }
};
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 08030f8..5d6c043 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -110,7 +110,7 @@
public boolean isGroupChangeAllowed(NotificationEntry entry) {
final boolean isGroupChangeAllowedForEntry =
mReorderingAllowed || mHeadsUpManager.isAlerting(entry.getKey());
- mIsSuppressingGroupChange |= isGroupChangeAllowedForEntry;
+ mIsSuppressingGroupChange |= !isGroupChangeAllowedForEntry;
return isGroupChangeAllowedForEntry;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
index c09122e..c9fc992 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.render.NodeController
data class NotifSection(
val sectioner: NotifSectioner,
@@ -24,4 +25,7 @@
) {
val label: String
get() = "Section($index, \"${sectioner.name}\")"
+
+ val headerController: NodeController?
+ get() = sectioner.headerNodeController
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index 9ee7db7..5a35127 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -174,8 +174,19 @@
str1 = suppressedParent?.key
str2 = keepingParent?.key
}, {
- "(Build $long1) Change of parent to '$str1' suppressed; " +
- "keeping parent '$str2'"
+ "(Build $long1) Change of parent to '$str1' suppressed; keeping parent '$str2'"
+ })
+ }
+
+ fun logGroupPruningSuppressed(
+ buildId: Int,
+ keepingParent: GroupEntry?
+ ) {
+ buffer.log(TAG, INFO, {
+ int1 = buildId
+ str1 = keepingParent?.key
+ }, {
+ "(Build $long1) Group pruning suppressed; keeping parent '$str1'"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
index b57f504..c8982d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
@@ -16,8 +16,12 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import android.annotation.Nullable;
+
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.collection.render.NodeSpec;
/**
* Pluggable for participating in notif sectioning. See {@link ShadeListBuilder#setSections}.
@@ -34,4 +38,12 @@
* notification. The first section to return true determines the section of the notification.
*/
public abstract boolean isInSection(ListEntry entry);
+
+ /**
+ * Returns an optional {@link NodeSpec} for the section header. If {@code null}, no header will
+ * be used for the section.
+ */
+ public @Nullable NodeController getHeaderNodeController() {
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
index c1f468a..e784ec6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
@@ -56,7 +56,7 @@
return false;
}
- return entry.getParent().getChildren().size() == 1;
+ return !isGroupSummary(entry) && entry.getParent().getChildren().size() == 1;
}
@Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
index 67f7b1c..727ce20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
@@ -39,9 +39,7 @@
throw RuntimeException("Not supported")
}
- fun getChildCount(): Int {
- throw RuntimeException("Not supported")
- }
+ fun getChildCount(): Int = 0
fun addChildAt(child: NodeController, index: Int) {
throw RuntimeException("Not supported")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
new file mode 100644
index 0000000..498b8e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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.systemui.statusbar.notification.collection.render
+
+import android.annotation.StringRes
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.statusbar.notification.dagger.HeaderClick
+import com.android.systemui.statusbar.notification.dagger.HeaderText
+import com.android.systemui.statusbar.notification.dagger.NodeLabel
+import com.android.systemui.statusbar.notification.dagger.SectionHeaderScope
+import com.android.systemui.statusbar.notification.stack.SectionHeaderView
+import javax.inject.Inject
+
+interface SectionHeaderController {
+ fun reinflateView(parent: ViewGroup)
+ val headerView: SectionHeaderView?
+ fun setOnClearAllClickListener(listener: View.OnClickListener)
+}
+
+@SectionHeaderScope
+internal class SectionHeaderNodeControllerImpl @Inject constructor(
+ @NodeLabel override val nodeLabel: String,
+ private val layoutInflater: LayoutInflater,
+ @HeaderText @StringRes private val headerTextResId: Int,
+ @HeaderClick private val onHeaderClickListener: View.OnClickListener
+) : NodeController, SectionHeaderController {
+
+ private var _view: SectionHeaderView? = null
+ private var clearAllClickListener: View.OnClickListener? = null
+
+ override fun reinflateView(parent: ViewGroup) {
+ var oldPos = -1
+ _view?.let { _view ->
+ _view.transientContainer?.removeView(_view)
+ if (_view.parent === parent) {
+ oldPos = parent.indexOfChild(_view)
+ parent.removeView(_view)
+ }
+ }
+ val inflated = layoutInflater.inflate(
+ R.layout.status_bar_notification_section_header,
+ parent,
+ false /* attachToRoot */)
+ as SectionHeaderView
+ inflated.setHeaderText(headerTextResId)
+ inflated.setOnHeaderClickListener(onHeaderClickListener)
+ clearAllClickListener?.let { inflated.setOnClearAllClickListener(it) }
+ if (oldPos != -1) {
+ parent.addView(inflated, oldPos)
+ }
+ _view = inflated
+ }
+
+ override val headerView: SectionHeaderView?
+ get() = _view
+
+ override fun setOnClearAllClickListener(listener: View.OnClickListener) {
+ clearAllClickListener = listener
+ _view?.setOnClearAllClickListener(listener)
+ }
+
+ override val view: View
+ get() = _view!!
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
index 019520f..22ca496 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
@@ -65,9 +65,7 @@
*
* For debugging purposes.
*/
- fun getViewLabel(view: View): String {
- return views[view]?.label ?: view.toString()
- }
+ fun getViewLabel(view: View): String = views[view]?.label ?: view.toString()
private fun detachChildren(
parentNode: ShadeNode,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 5243854..c1a63e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -42,46 +42,34 @@
private val rootController = RootNodeController(listContainer, View(context))
private val viewDiffer = ShadeViewDiffer(rootController, logger)
- fun attach(listBuilder: ShadeListBuilder) {
- listBuilder.setOnRenderListListener(::onNewNotifTree)
- }
+ fun attach(listBuilder: ShadeListBuilder) =
+ listBuilder.setOnRenderListListener(::onNewNotifTree)
- private fun onNewNotifTree(tree: List<ListEntry>) {
- viewDiffer.applySpec(buildTree(tree))
- }
+ private fun onNewNotifTree(tree: List<ListEntry>) = viewDiffer.applySpec(buildTree(tree))
private fun buildTree(notifList: List<ListEntry>): NodeSpec {
- val root = NodeSpecImpl(null, rootController)
-
- for (entry in notifList) {
- // TODO: Add section header logic here
- root.children.add(buildNotifNode(entry, root))
+ val root = NodeSpecImpl(null, rootController).apply {
+ // Insert first section header, if present
+ notifList.firstOrNull()?.section?.headerController?.let {
+ children.add(NodeSpecImpl(this, it))
+ }
+ notifList.asSequence().zipWithNext().forEach { (prev, entry) ->
+ // Insert new header if the section has changed between two entries
+ entry.section.takeIf { it != prev.section }?.headerController?.let {
+ children.add(NodeSpecImpl(this, it))
+ }
+ children.add(buildNotifNode(entry, this))
+ }
}
-
notificationIconAreaController.updateNotificationIcons(notifList)
return root
}
- private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec {
- return when (entry) {
- is NotificationEntry -> {
- NodeSpecImpl(parent, viewBarn.requireView(entry))
- }
- is GroupEntry -> {
- val groupNode = NodeSpecImpl(
- parent,
- viewBarn.requireView(checkNotNull(entry.summary)))
-
- for (childEntry in entry.children) {
- groupNode.children.add(buildNotifNode(childEntry, groupNode))
- }
-
- groupNode
- }
- else -> {
- throw RuntimeException("Unexpected entry: $entry")
- }
- }
+ private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec = when (entry) {
+ is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry))
+ is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary)))
+ .apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } }
+ else -> throw RuntimeException("Unexpected entry: $entry")
}
}
@@ -91,12 +79,11 @@
private val viewBarn: NotifViewBarn,
private val notificationIconAreaController: NotificationIconAreaController
) {
- fun create(listContainer: NotificationListContainer): ShadeViewManager {
- return ShadeViewManager(
- context,
- listContainer,
- logger,
- viewBarn,
- notificationIconAreaController)
- }
+ fun create(listContainer: NotificationListContainer) =
+ ShadeViewManager(
+ context,
+ listContainer,
+ logger,
+ viewBarn,
+ notificationIconAreaController)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
new file mode 100644
index 0000000..179d49c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2020 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.systemui.statusbar.notification.dagger
+
+import android.annotation.StringRes
+import android.content.Intent
+import android.provider.Settings
+import android.view.View
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.notification.collection.render.NodeController
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderNodeControllerImpl
+import dagger.Binds
+import dagger.BindsInstance
+import dagger.Module
+import dagger.Provides
+import dagger.Subcomponent
+import javax.inject.Provider
+import javax.inject.Qualifier
+import javax.inject.Scope
+
+@Module(subcomponents = [SectionHeaderControllerSubcomponent::class])
+object NotificationSectionHeadersModule {
+
+ @Provides
+ @HeaderClick
+ @JvmStatic fun providesOnHeaderClickListener(
+ activityStarter: ActivityStarter
+ ) = View.OnClickListener {
+ activityStarter.startActivity(
+ Intent(Settings.ACTION_NOTIFICATION_SETTINGS),
+ true /* onlyProvisioned */,
+ true /* dismissShade */,
+ Intent.FLAG_ACTIVITY_SINGLE_TOP)
+ }
+
+ @Provides
+ @IncomingHeader
+ @SysUISingleton
+ @JvmStatic fun providesIncomingHeaderSubcomponent(
+ builder: Provider<SectionHeaderControllerSubcomponent.Builder>
+ ) = builder.get()
+ .nodeLabel("incoming header")
+ .headerText(R.string.notification_section_header_incoming)
+ .build()
+
+ @Provides
+ @AlertingHeader
+ @SysUISingleton
+ @JvmStatic fun providesAlertingHeaderSubcomponent(
+ builder: Provider<SectionHeaderControllerSubcomponent.Builder>
+ ) = builder.get()
+ .nodeLabel("alerting header")
+ .headerText(R.string.notification_section_header_alerting)
+ .build()
+
+ @Provides
+ @PeopleHeader
+ @SysUISingleton
+ @JvmStatic fun providesPeopleHeaderSubcomponent(
+ builder: Provider<SectionHeaderControllerSubcomponent.Builder>
+ ) = builder.get()
+ .nodeLabel("people header")
+ .headerText(R.string.notification_section_header_conversations)
+ .build()
+
+ @Provides
+ @SilentHeader
+ @SysUISingleton
+ @JvmStatic fun providesSilentHeaderSubcomponent(
+ builder: Provider<SectionHeaderControllerSubcomponent.Builder>
+ ) = builder.get()
+ .nodeLabel("silent header")
+ .headerText(R.string.notification_section_header_gentle)
+ .build()
+
+ @Provides
+ @SilentHeader
+ @JvmStatic fun providesSilentHeaderNodeController(
+ @SilentHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.nodeController
+
+ @Provides
+ @SilentHeader
+ @JvmStatic fun providesSilentHeaderController(
+ @SilentHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.headerController
+
+ @Provides
+ @AlertingHeader
+ @JvmStatic fun providesAlertingHeaderNodeController(
+ @AlertingHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.nodeController
+
+ @Provides
+ @AlertingHeader
+ @JvmStatic fun providesAlertingHeaderController(
+ @AlertingHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.headerController
+
+ @Provides
+ @PeopleHeader
+ @JvmStatic fun providesPeopleHeaderNodeController(
+ @PeopleHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.nodeController
+
+ @Provides
+ @PeopleHeader
+ @JvmStatic fun providesPeopleHeaderController(
+ @PeopleHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.headerController
+
+ @Provides
+ @IncomingHeader
+ @JvmStatic fun providesIncomingHeaderNodeController(
+ @IncomingHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.nodeController
+
+ @Provides
+ @IncomingHeader
+ @JvmStatic fun providesIncomingHeaderController(
+ @IncomingHeader subcomponent: SectionHeaderControllerSubcomponent
+ ) = subcomponent.headerController
+}
+
+@Subcomponent(modules = [ SectionHeaderBindingModule::class ])
+@SectionHeaderScope
+interface SectionHeaderControllerSubcomponent {
+
+ val nodeController: NodeController
+ val headerController: SectionHeaderController
+
+ @Subcomponent.Builder
+ interface Builder {
+ fun build(): SectionHeaderControllerSubcomponent
+ @BindsInstance fun nodeLabel(@NodeLabel nodeLabel: String): Builder
+ @BindsInstance fun headerText(@HeaderText @StringRes headerText: Int): Builder
+ }
+}
+
+@Module
+private abstract class SectionHeaderBindingModule {
+ @Binds abstract fun bindsNodeController(impl: SectionHeaderNodeControllerImpl): NodeController
+ @Binds abstract fun bindsSectionHeaderController(
+ impl: SectionHeaderNodeControllerImpl
+ ): SectionHeaderController
+}
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class HeaderText
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class IncomingHeader
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class AlertingHeader
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class SilentHeader
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class PeopleHeader
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class NodeLabel
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class HeaderClick
+
+@Scope
+@Retention(AnnotationRetention.BINARY)
+annotation class SectionHeaderScope
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index ea86d253..2327063 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -88,7 +88,7 @@
/**
* Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
*/
-@Module
+@Module(includes = { NotificationSectionHeadersModule.class })
public interface NotificationsModule {
/** Provides an instance of {@link NotificationEntryManager} */
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index ff7793d..4f7e14b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -18,23 +18,21 @@
import android.annotation.ColorInt
import android.annotation.IntDef
import android.annotation.LayoutRes
-import android.content.Intent
-import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.media.KeyguardMediaController
-import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
-import com.android.systemui.statusbar.notification.people.DataListener
-import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter
-import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary
-import com.android.systemui.statusbar.notification.people.PersonViewModel
-import com.android.systemui.statusbar.notification.people.Subscription
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController
+import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager
+import com.android.systemui.statusbar.notification.dagger.AlertingHeader
+import com.android.systemui.statusbar.notification.dagger.IncomingHeader
+import com.android.systemui.statusbar.notification.dagger.PeopleHeader
+import com.android.systemui.statusbar.notification.dagger.SilentHeader
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView
@@ -46,19 +44,25 @@
import javax.inject.Inject
/**
- * Manages the boundaries of the two notification sections (high priority and low priority). Also
- * shows/hides the headers for those sections where appropriate.
+ * Manages the boundaries of the notification sections (incoming, conversations, high priority, and
+ * low priority).
+ *
+ * In the legacy notification pipeline, this is responsible for correctly positioning all section
+ * headers after the [NotificationStackScrollLayout] has had notifications added/removed/changed. In
+ * the new pipeline, this is handled as part of the [ShadeViewManager].
*
* TODO: Move remaining sections logic from NSSL into this class.
*/
class NotificationSectionsManager @Inject internal constructor(
- private val activityStarter: ActivityStarter,
private val statusBarStateController: StatusBarStateController,
private val configurationController: ConfigurationController,
- private val peopleHubViewAdapter: PeopleHubViewAdapter,
private val keyguardMediaController: KeyguardMediaController,
private val sectionsFeatureManager: NotificationSectionsFeatureManager,
- private val logger: NotificationSectionsLogger
+ private val logger: NotificationSectionsLogger,
+ @IncomingHeader private val incomingHeaderController: SectionHeaderController,
+ @PeopleHeader private val peopleHeaderController: SectionHeaderController,
+ @AlertingHeader private val alertingHeaderController: SectionHeaderController,
+ @SilentHeader private val silentHeaderController: SectionHeaderController
) : SectionProvider {
private val configurationListener = object : ConfigurationController.ConfigurationListener {
@@ -67,46 +71,25 @@
}
}
- private val peopleHubViewBoundary: PeopleHubViewBoundary = object : PeopleHubViewBoundary {
- override fun setVisible(isVisible: Boolean) {
- if (peopleHubVisible != isVisible) {
- peopleHubVisible = isVisible
- if (initialized) {
- updateSectionBoundaries("PeopleHub visibility changed")
- }
- }
- }
-
- override val associatedViewForClickAnimation: View
- get() = peopleHeaderView!!
-
- override val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
- get() = peopleHeaderView!!.personViewAdapters
- }
-
private lateinit var parent: NotificationStackScrollLayout
private var initialized = false
private var onClearSilentNotifsClickListener: View.OnClickListener? = null
- @get:VisibleForTesting
- var silentHeaderView: SectionHeaderView? = null
- private set
+ @VisibleForTesting
+ val silentHeaderView: SectionHeaderView?
+ get() = silentHeaderController.headerView
- @get:VisibleForTesting
- var alertingHeaderView: SectionHeaderView? = null
- private set
+ @VisibleForTesting
+ val alertingHeaderView: SectionHeaderView?
+ get() = alertingHeaderController.headerView
- @get:VisibleForTesting
- var incomingHeaderView: SectionHeaderView? = null
- private set
+ @VisibleForTesting
+ val incomingHeaderView: SectionHeaderView?
+ get() = incomingHeaderController.headerView
- @get:VisibleForTesting
- var peopleHeaderView: PeopleHubView? = null
- private set
-
- @set:VisibleForTesting
- var peopleHubVisible = false
- private var peopleHubSubscription: Subscription? = null
+ @VisibleForTesting
+ val peopleHeaderView: SectionHeaderView?
+ get() = peopleHeaderController.headerView
@get:VisibleForTesting
var mediaControlsView: MediaHeaderView? = null
@@ -150,34 +133,10 @@
* Reinflates the entire notification header, including all decoration views.
*/
fun reinflateViews(layoutInflater: LayoutInflater) {
- silentHeaderView = reinflateView(
- silentHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
- ).apply {
- setHeaderText(R.string.notification_section_header_gentle)
- setOnHeaderClickListener { onGentleHeaderClick() }
- setOnClearAllClickListener { onClearGentleNotifsClick(it) }
- }
- alertingHeaderView = reinflateView(
- alertingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
- ).apply {
- setHeaderText(R.string.notification_section_header_alerting)
- setOnHeaderClickListener { onGentleHeaderClick() }
- }
- peopleHubSubscription?.unsubscribe()
- peopleHubSubscription = null
- peopleHeaderView = reinflateView(peopleHeaderView, layoutInflater, R.layout.people_strip)
- .apply {
- setOnHeaderClickListener(View.OnClickListener { onGentleHeaderClick() })
- }
- if (ENABLE_SNOOZED_CONVERSATION_HUB) {
- peopleHubSubscription = peopleHubViewAdapter.bindView(peopleHubViewBoundary)
- }
- incomingHeaderView = reinflateView(
- incomingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
- ).apply {
- setHeaderText(R.string.notification_section_header_incoming)
- setOnHeaderClickListener { onGentleHeaderClick() }
- }
+ silentHeaderController.reinflateView(parent)
+ alertingHeaderController.reinflateView(parent)
+ peopleHeaderController.reinflateView(parent)
+ incomingHeaderController.reinflateView(parent)
mediaControlsView =
reinflateView(mediaControlsView, layoutInflater, R.layout.keyguard_media_header)
.also(keyguardMediaController::attach)
@@ -296,7 +255,6 @@
// target, but won't be once they are moved / removed after the pass has completed.
val showHeaders = statusBarStateController.state != StatusBarState.KEYGUARD
- val usingPeopleFiltering = sectionsFeatureManager.isFilteringEnabled()
val usingMediaControls = sectionsFeatureManager.isMediaControlsEnabled()
val mediaState = mediaControlsView?.let(::expandableViewHeaderState)
@@ -319,7 +277,6 @@
).filterNotNull()
var peopleNotifsPresent = false
- var lastNotifIndex = 0
var nextBucket: Int? = null
var inIncomingSection = false
@@ -373,30 +330,9 @@
// Check if there are any people notifications
peopleNotifsPresent = peopleNotifsPresent || row.entry.bucket == BUCKET_PEOPLE
-
- if (nextBucket == null) {
- lastNotifIndex = i
- }
nextBucket = row.entry.bucket
}
- if (showHeaders && usingPeopleFiltering && peopleHubVisible) {
- peopleState?.targetPosition = peopleState?.targetPosition
- // Insert the people header even if there are no people visible, in order to
- // show the hub. Put it directly above the next header.
- ?: alertingState?.targetPosition
- ?: gentleState?.targetPosition
- // Put it at the end of the list.
- ?: lastNotifIndex
-
- // Offset the target to account for the current position of the people header.
- peopleState?.targetPosition = peopleState?.currentPosition?.let { current ->
- peopleState.targetPosition?.let { target ->
- if (current < target) target - 1 else target
- }
- }
- }
-
mediaState?.targetPosition = if (usingMediaControls) 0 else null
logger.logStr("New header target positions:")
@@ -420,14 +356,6 @@
.hasActiveClearableNotifications(NotificationStackScrollLayout.ROWS_GENTLE)
setAreThereDismissableGentleNotifs(hasActiveClearableNotifications)
}
- peopleHeaderView?.run {
- canSwipe = showHeaders && peopleHubVisible && !peopleNotifsPresent
- peopleState?.targetPosition?.let { targetPosition ->
- if (targetPosition != peopleState.currentPosition) {
- resetTranslation()
- }
- }
- }
}
private sealed class SectionBounds {
@@ -513,31 +441,13 @@
}
}
- private fun onGentleHeaderClick() {
- val intent = Intent(Settings.ACTION_NOTIFICATION_SETTINGS)
- activityStarter.startActivity(
- intent,
- true,
- true,
- Intent.FLAG_ACTIVITY_SINGLE_TOP)
- }
-
- private fun onClearGentleNotifsClick(v: View) {
- onClearSilentNotifsClickListener?.onClick(v)
- }
-
/** Listener for when the "clear all" button is clicked on the gentle notification header. */
fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) {
onClearSilentNotifsClickListener = listener
}
- fun hidePeopleRow() {
- peopleHubVisible = false
- updateSectionBoundaries("PeopleHub dismissed")
- }
-
fun setHeaderForegroundColor(@ColorInt color: Int) {
- peopleHeaderView?.setTextColor(color)
+ peopleHeaderView?.setForegroundColor(color)
silentHeaderView?.setForegroundColor(color)
alertingHeaderView?.setForegroundColor(color)
}
@@ -545,7 +455,6 @@
companion object {
private const val TAG = "NotifSectionsManager"
private const val DEBUG = false
- private const val ENABLE_SNOOZED_CONVERSATION_HUB = false
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b33aa57..e0e3013 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -16,14 +16,10 @@
package com.android.systemui.statusbar.notification.stack;
-import static android.service.notification.NotificationStats.DISMISSAL_SHADE;
-import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
-import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -49,10 +45,8 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.notification.NotificationListenerService;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -83,8 +77,6 @@
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.keyguard.KeyguardSliceView;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
@@ -96,27 +88,20 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -136,7 +121,6 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Assert;
import java.io.FileDescriptor;
@@ -173,7 +157,6 @@
*/
private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
- private final DynamicPrivacyController mDynamicPrivacyController;
private final SysuiStatusBarStateController mStatusbarStateController;
private ExpandHelper mExpandHelper;
@@ -225,7 +208,6 @@
private int mBottomMargin;
private int mBottomInset = 0;
private float mQsExpansionFraction;
- private int mCurrentUserId;
/**
* The algorithm which calculates the properties for our children
@@ -468,12 +450,7 @@
private int mHeadsUpInset;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private final Rect mTmpRect = new Rect();
- private final FeatureFlags mFeatureFlags;
- private final NotifPipeline mNotifPipeline;
- private final NotifCollection mNotifCollection;
- private final NotificationEntryManager mEntryManager;
- private final IStatusBarService mBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ private DismissAllAnimationListener mDismissAllAnimationListener;
@VisibleForTesting
protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
protected final UiEventLogger mUiEventLogger;
@@ -553,18 +530,13 @@
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
NotificationRoundnessManager notificationRoundnessManager,
- DynamicPrivacyController dynamicPrivacyController,
SysuiStatusBarStateController statusbarStateController,
NotificationSectionsManager notificationSectionsManager,
ForegroundServiceSectionController fgsSectionController,
ForegroundServiceDismissalFeatureController fgsFeatureController,
- FeatureFlags featureFlags,
- NotifPipeline notifPipeline,
- NotificationEntryManager entryManager,
- NotifCollection notifCollection,
- UiEventLogger uiEventLogger,
GroupMembershipManager groupMembershipManager,
- GroupExpansionManager groupExpansionManager
+ GroupExpansionManager groupExpansionManager,
+ UiEventLogger uiEventLogger
) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -576,7 +548,8 @@
mSectionsManager.initialize(this, LayoutInflater.from(context));
mSectionsManager.setOnClearSilentNotifsClickListener(v -> {
// Leave the shade open if there will be other notifs left over to clear
- final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
+ final boolean closeShade =
+ !mController.hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
clearNotifications(ROWS_GENTLE, closeShade);
});
mSections = mSectionsManager.createSectionsForBuckets();
@@ -613,37 +586,8 @@
mDebugPaint.setTextSize(25f);
}
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
-
- TunerService tunerService = Dependency.get(TunerService.class);
- tunerService.addTunable((key, newValue) -> {
- if (key.equals(HIGH_PRIORITY)) {
- mHighPriorityBeforeSpeedBump = "1".equals(newValue);
- }
- }, HIGH_PRIORITY);
-
- mFeatureFlags = featureFlags;
- mNotifPipeline = notifPipeline;
- mEntryManager = entryManager;
- mNotifCollection = notifCollection;
- if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
- @Override
- public void onEntryUpdated(NotificationEntry entry) {
- NotificationStackScrollLayout.this.onEntryUpdated(entry);
- }
- });
- } else {
- mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
- @Override
- public void onPreEntryUpdated(NotificationEntry entry) {
- NotificationStackScrollLayout.this.onEntryUpdated(entry);
- }
- });
- }
mGroupMembershipManager = groupMembershipManager;
mGroupExpansionManager = groupExpansionManager;
-
- mDynamicPrivacyController = dynamicPrivacyController;
mStatusbarStateController = statusbarStateController;
initializeForegroundServiceSection(fgsFeatureController);
mUiEventLogger = uiEventLogger;
@@ -707,10 +651,13 @@
if (mFooterView == null) {
return;
}
- boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL);
- boolean showFooterView = (showDismissView || hasActiveNotifications())
+ // TODO: move this logic to controller, which will invoke updateFooterView directly
+ boolean showDismissView = mClearAllEnabled &&
+ mController.hasActiveClearableNotifications(ROWS_ALL);
+ RemoteInputController remoteInputController = mRemoteInputManager.getController();
+ boolean showFooterView = (showDismissView || mController.hasActiveNotifications())
&& mStatusBarState != StatusBarState.KEYGUARD
- && !mRemoteInputManager.getController().isRemoteInputActive();
+ && (remoteInputController == null || !remoteInputController.isRemoteInputActive());
boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
@@ -721,22 +668,8 @@
* Return whether there are any clearable notifications
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
- if (mDynamicPrivacyController.isInLockedDownShade()) {
- return false;
- }
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (!(child instanceof ExpandableNotificationRow)) {
- continue;
- }
- final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (row.canViewBeDismissed() && matchesSelection(row, selection)) {
- return true;
- }
- }
- return false;
+ boolean hasActiveClearableNotifications(@SelectedRows int selection) {
+ return mController.hasActiveClearableNotifications(selection);
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5292,8 +5225,6 @@
updateFooter();
requestChildrenUpdate();
onUpdateRowStates();
-
- mEntryManager.updateNotifications("StatusBar state changed");
updateVisibility();
}
@@ -5697,10 +5628,6 @@
return mController;
}
- void setCurrentUserid(int userId) {
- mCurrentUserId = userId;
- }
-
void addSwipedOutView(View v) {
mSwipedOutViews.add(v);
}
@@ -5774,6 +5701,14 @@
return mCheckForLeavebehind;
}
+ void setDismissAllAnimationListener(DismissAllAnimationListener dismissAllAnimationListener) {
+ mDismissAllAnimationListener = dismissAllAnimationListener;
+ }
+
+ public void setHighPriorityBeforeSpeedBump(boolean highPriorityBeforeSpeedBump) {
+ mHighPriorityBeforeSpeedBump = highPriorityBeforeSpeedBump;
+ }
+
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@@ -5852,7 +5787,7 @@
mSwipeHelper.resetExposedMenuView(animate, force);
}
- private static boolean matchesSelection(
+ static boolean matchesSelection(
ExpandableNotificationRow row,
@SelectedRows int selection) {
switch (selection) {
@@ -6127,7 +6062,7 @@
// --------------------- NotificationEntryManager/NotifPipeline methods ------------------------
- private void onEntryUpdated(NotificationEntry entry) {
+ void onEntryUpdated(NotificationEntry entry) {
// If the row already exists, the user may have performed a dismiss action on the
// notification. Since it's not clearable we should snap it back.
if (entry.rowExists() && !entry.getSbn().isClearable()) {
@@ -6135,73 +6070,17 @@
}
}
- private boolean hasActiveNotifications() {
- if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- return !mNotifPipeline.getShadeList().isEmpty();
- } else {
- return mEntryManager.hasActiveNotifications();
- }
- }
-
/**
* Called after the animations for a "clear all notifications" action has ended.
*/
private void onDismissAllAnimationsEnd(
List<ExpandableNotificationRow> viewsToRemove,
@SelectedRows int selectedRows) {
- if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- if (selectedRows == ROWS_ALL) {
- mNotifCollection.dismissAllNotifications(mCurrentUserId);
- } else {
- final List<Pair<NotificationEntry, DismissedByUserStats>>
- entriesWithRowsDismissedFromShade = new ArrayList<>();
- final int numVisibleEntries = mNotifPipeline.getShadeListCount();
- for (int i = 0; i < viewsToRemove.size(); i++) {
- final NotificationEntry entry = viewsToRemove.get(i).getEntry();
- entriesWithRowsDismissedFromShade.add(
- new Pair<NotificationEntry, DismissedByUserStats>(
- entry,
- getDismissedByUserStats(entry, numVisibleEntries)));
- }
- mNotifCollection.dismissNotifications(entriesWithRowsDismissedFromShade);
- }
- } else {
- for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
- if (canChildBeDismissed(rowToRemove)) {
- mEntryManager.performRemoveNotification(
- rowToRemove.getEntry().getSbn(),
- getDismissedByUserStats(
- rowToRemove.getEntry(),
- mEntryManager.getActiveNotificationsCount()),
- NotificationListenerService.REASON_CANCEL_ALL);
- } else {
- rowToRemove.resetTranslation();
- }
- }
- if (selectedRows == ROWS_ALL) {
- try {
- mBarService.onClearAllNotifications(mCurrentUserId);
- } catch (Exception ex) {
- }
- }
+ if (mDismissAllAnimationListener != null) {
+ mDismissAllAnimationListener.onAnimationEnd(viewsToRemove, selectedRows);
}
}
- private DismissedByUserStats getDismissedByUserStats(
- NotificationEntry entry,
- int numVisibleEntries
- ) {
- return new DismissedByUserStats(
- DISMISSAL_SHADE,
- DISMISS_SENTIMENT_NEUTRAL,
- NotificationVisibility.obtain(
- entry.getKey(),
- entry.getRanking().getRank(),
- numVisibleEntries,
- true,
- NotificationLogger.getNotificationLocation(entry)));
- }
-
public void setKeyguardMediaControllorVisible(boolean keyguardMediaControllorVisible) {
mKeyguardMediaControllorVisible = keyguardMediaControllorVisible;
}
@@ -6218,7 +6097,8 @@
/* Only ever called as a consequence of a lockscreen expansion gesture. */
@Override
public boolean onDraggedDown(View startingChild, int dragLengthY) {
- boolean canDragDown = hasActiveNotifications() || mKeyguardMediaControllorVisible;
+ boolean canDragDown =
+ mController.hasActiveNotifications() || mKeyguardMediaControllorVisible;
if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) {
mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_SHADE,
@@ -6236,7 +6116,7 @@
}
return true;
- } else if (mDynamicPrivacyController.isInLockedDownShade()) {
+ } else if (mController.isInLockedDownShade()) {
mStatusbarStateController.setLeaveOpenOnKeyguardHide(true);
mStatusBar.dismissKeyguardThenExecute(() -> false /* dismissAction */,
null /* cancelRunnable */, false /* afterKeyguardGone */);
@@ -6280,7 +6160,7 @@
if (isDragDownAnywhereEnabled()) {
return true;
}
- if (mDynamicPrivacyController.isInLockedDownShade()) {
+ if (mController.isInLockedDownShade()) {
if (view == null) {
// Dragging down is allowed in general
return true;
@@ -6424,7 +6304,7 @@
/** Enum for selecting some or all notification rows (does not included non-notif views). */
@Retention(SOURCE)
@IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE})
- public @interface SelectedRows {}
+ @interface SelectedRows {}
/** All rows representing notifs. */
public static final int ROWS_ALL = 0;
/** Only rows where entry.isHighPriority() is true. */
@@ -6466,4 +6346,9 @@
interface KeyguardBypassEnabledProvider {
boolean getBypassEnabled();
}
+
+ interface DismissAllAnimationListener {
+ void onAnimationEnd(
+ List<ExpandableNotificationRow> viewsToRemove, @SelectedRows int selectedRows);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 81e6258..88b7fab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -16,15 +16,28 @@
package com.android.systemui.statusbar.notification.stack;
+import static android.service.notification.NotificationStats.DISMISSAL_SHADE;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
+
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_HIGH_PRIORITY;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.SelectedRows;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.canChildBeDismissed;
+import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.util.Pair;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
@@ -35,6 +48,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.ExpandHelper;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
@@ -47,6 +62,7 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -56,11 +72,20 @@
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.ShadeViewRefactor;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
+import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -82,6 +107,8 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.BiConsumer;
import javax.inject.Inject;
@@ -110,6 +137,11 @@
private final Resources mResources;
private final NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
private final ScrimController mScrimController;
+ private final FeatureFlags mFeatureFlags;
+ private final NotifPipeline mNotifPipeline;
+ private final NotifCollection mNotifCollection;
+ private final NotificationEntryManager mNotificationEntryManager;
+ private final IStatusBarService mIStatusBarService;
private final KeyguardMediaController mKeyguardMediaController;
private final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mKeyguardBypassController;
@@ -117,6 +149,7 @@
private final NotificationLockscreenUserManager mLockscreenUserManager;
// TODO: StatusBar should be encapsulated behind a Controller
private final StatusBar mStatusBar;
+ private final SectionHeaderController mSilentHeaderController;
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
@@ -206,13 +239,13 @@
mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(),
mLockscreenUserManager.isAnyProfilePublicMode());
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
+ mNotificationEntryManager.updateNotifications("StatusBar state changed");
}
};
private final UserChangedListener mLockscreenUserChangeListener = new UserChangedListener() {
@Override
public void onUserChanged(int userId) {
- mView.setCurrentUserid(userId);
mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode());
}
};
@@ -359,10 +392,6 @@
row.performDismissWithBlockingHelper(false /* fromAccessibility */);
}
- if (view instanceof PeopleHubView) {
- mNotificationSectionsManager.hidePeopleRow();
- }
-
if (!isBlockingHelperShown) {
mView.addSwipedOutView(view);
}
@@ -523,7 +552,13 @@
StatusBar statusBar,
ScrimController scrimController,
NotificationGroupManagerLegacy legacyGroupManager,
- GroupExpansionManager groupManager) {
+ GroupExpansionManager groupManager,
+ @SilentHeader SectionHeaderController silentHeaderController,
+ FeatureFlags featureFlags,
+ NotifPipeline notifPipeline,
+ NotifCollection notifCollection,
+ NotificationEntryManager notificationEntryManager,
+ IStatusBarService iStatusBarService) {
mAllowLongPress = allowLongPress;
mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager;
@@ -547,7 +582,6 @@
groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> {
mView.onGroupExpandChanged(changedRow, expanded);
});
-
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
@Override
public void onGroupCreatedFromChildren(NotificationGroup group) {
@@ -559,6 +593,12 @@
mStatusBar.requestNotificationUpdate("onGroupsChanged");
}
});
+ mSilentHeaderController = silentHeaderController;
+ mFeatureFlags = featureFlags;
+ mNotifPipeline = notifPipeline;
+ mNotifCollection = notifCollection;
+ mNotificationEntryManager = notificationEntryManager;
+ mIStatusBarService = iStatusBarService;
}
public void attach(NotificationStackScrollLayout view) {
@@ -566,6 +606,7 @@
mView.setController(this);
mView.setTouchHandler(new TouchHandler());
mView.setStatusBar(mStatusBar);
+ mView.setDismissAllAnimationListener(this::onAnimationEnd);
mSwipeHelper = mNotificationSwipeHelperBuilder
.setSwipeDirection(SwipeHelper.X)
@@ -573,6 +614,22 @@
.setOnMenuEventListener(mMenuEventListener)
.build();
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
+ @Override
+ public void onEntryUpdated(NotificationEntry entry) {
+ mView.onEntryUpdated(entry);
+ }
+ });
+ } else {
+ mNotificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onPreEntryUpdated(NotificationEntry entry) {
+ mView.onEntryUpdated(entry);
+ }
+ });
+ }
+
mView.initView(mView.getContext(), mKeyguardBypassController::getBypassEnabled,
mSwipeHelper);
@@ -584,7 +641,6 @@
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
- mView.setCurrentUserid(mLockscreenUserManager.getCurrentUserId());
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
mResources.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
@@ -594,12 +650,19 @@
mTunerService.addTunable(
(key, newValue) -> {
- if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) {
- mView.updateDismissRtlSetting("1".equals(newValue));
- } else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) {
- updateFooter();
+ switch (key) {
+ case Settings.Secure.NOTIFICATION_DISMISS_RTL:
+ mView.updateDismissRtlSetting("1".equals(newValue));
+ break;
+ case Settings.Secure.NOTIFICATION_HISTORY_ENABLED:
+ updateFooter();
+ break;
+ case HIGH_PRIORITY:
+ mView.setHighPriorityBeforeSpeedBump("1".equals(newValue));
+ break;
}
},
+ HIGH_PRIORITY,
Settings.Secure.NOTIFICATION_DISMISS_RTL,
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
@@ -624,6 +687,7 @@
mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
}
mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
+ mSilentHeaderController.setOnClearAllClickListener(v -> clearSilentNotifications());
}
public void addOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) {
@@ -680,12 +744,12 @@
}
public void setOverscrollTopChangedListener(
- NotificationStackScrollLayout.OnOverscrollTopChangedListener listener) {
+ OnOverscrollTopChangedListener listener) {
mView.setOverscrollTopChangedListener(listener);
}
public void setOnEmptySpaceClickListener(
- NotificationStackScrollLayout.OnEmptySpaceClickListener listener) {
+ OnEmptySpaceClickListener listener) {
mView.setOnEmptySpaceClickListener(listener);
}
@@ -1003,9 +1067,26 @@
mView.setPulsing(pulsing, animatePulse);
}
- public boolean hasActiveClearableNotifications(
- @NotificationStackScrollLayout.SelectedRows int selection) {
- return mView.hasActiveClearableNotifications(selection);
+ /**
+ * Return whether there are any clearable notifications
+ */
+ public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
+ if (mDynamicPrivacyController.isInLockedDownShade()) {
+ return false;
+ }
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (!(child instanceof ExpandableNotificationRow)) {
+ continue;
+ }
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ if (row.canViewBeDismissed() &&
+ NotificationStackScrollLayout.matchesSelection(row, selection)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -1116,6 +1197,29 @@
mView.resetCheckSnoozeLeavebehind();
}
+ private DismissedByUserStats getDismissedByUserStats(
+ NotificationEntry entry,
+ int numVisibleEntries
+ ) {
+ return new DismissedByUserStats(
+ DISMISSAL_SHADE,
+ DISMISS_SENTIMENT_NEUTRAL,
+ NotificationVisibility.obtain(
+ entry.getKey(),
+ entry.getRanking().getRank(),
+ numVisibleEntries,
+ true,
+ NotificationLogger.getNotificationLocation(entry)));
+ }
+
+ boolean hasActiveNotifications() {
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ return !mNotifPipeline.getShadeList().isEmpty();
+ } else {
+ return mNotificationEntryManager.hasActiveNotifications();
+ }
+ }
+
public void closeControlsIfOutsideTouch(MotionEvent ev) {
NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
@@ -1138,6 +1242,57 @@
}
}
+ public void clearSilentNotifications() {
+ // Leave the shade open if there will be other notifs left over to clear
+ final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
+ mView.clearNotifications(ROWS_GENTLE, closeShade);
+ }
+
+ private void onAnimationEnd(List<ExpandableNotificationRow> viewsToRemove, int selectedRows) {
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ if (selectedRows == ROWS_ALL) {
+ mNotifCollection.dismissAllNotifications(
+ mLockscreenUserManager.getCurrentUserId());
+ } else {
+ final List<Pair<NotificationEntry, DismissedByUserStats>>
+ entriesWithRowsDismissedFromShade = new ArrayList<>();
+ final int numVisibleEntries = mNotifPipeline.getShadeListCount();
+ for (ExpandableNotificationRow row : viewsToRemove) {
+ final NotificationEntry entry = row.getEntry();
+ entriesWithRowsDismissedFromShade.add(
+ new Pair<>(
+ entry,
+ getDismissedByUserStats(entry, numVisibleEntries)));
+ }
+ mNotifCollection.dismissNotifications(entriesWithRowsDismissedFromShade);
+ }
+ } else {
+ for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+ if (canChildBeDismissed(rowToRemove)) {
+ mNotificationEntryManager.performRemoveNotification(
+ rowToRemove.getEntry().getSbn(),
+ getDismissedByUserStats(
+ rowToRemove.getEntry(),
+ mNotificationEntryManager.getActiveNotificationsCount()),
+ NotificationListenerService.REASON_CANCEL_ALL);
+ } else {
+ rowToRemove.resetTranslation();
+ }
+ }
+ if (selectedRows == ROWS_ALL) {
+ try {
+ mIStatusBarService.onClearAllNotifications(
+ mLockscreenUserManager.getCurrentUserId());
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+
+ public boolean isInLockedDownShade() {
+ return mDynamicPrivacyController.isInLockedDownShade();
+ }
+
private class NotificationListContainerImpl implements NotificationListContainer {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index 5777ba1..99ec7548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -97,7 +97,7 @@
/**
* Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything).
*/
- void setOnHeaderClickListener(View.OnClickListener listener) {
+ public void setOnHeaderClickListener(View.OnClickListener listener) {
mLabelClickListener = listener;
mLabelView.setOnClickListener(listener);
}
@@ -112,7 +112,7 @@
}
/** Fired when the user clicks on the "X" button on the far right of the header. */
- void setOnClearAllClickListener(View.OnClickListener listener) {
+ public void setOnClearAllClickListener(View.OnClickListener listener) {
mOnClearClickListener = listener;
mClearAllButton.setOnClickListener(listener);
}
@@ -122,7 +122,8 @@
return true;
}
- void setHeaderText(@StringRes int resId) {
+ /** Sets text to be displayed in the header */
+ public void setHeaderText(@StringRes int resId) {
mLabelTextId = resId;
mLabelView.setText(resId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 09034c0..3665c39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -25,26 +25,21 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
-import android.util.MathUtils;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.WindowInsets;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardHostViewController;
+import com.android.keyguard.KeyguardRootViewController;
import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.dagger.ContainerView;
-import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
+import com.android.keyguard.dagger.RootView;
import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -57,18 +52,16 @@
/**
* A class which manages the bouncer on the lockscreen.
*/
-@KeyguardBouncerScope
public class KeyguardBouncer {
private static final String TAG = "KeyguardBouncer";
static final long BOUNCER_FACE_DELAY = 1200;
- static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
+ public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
static final float EXPANSION_HIDDEN = 1f;
static final float EXPANSION_VISIBLE = 0f;
protected final Context mContext;
protected final ViewMediatorCallback mCallback;
- protected final LockPatternUtils mLockPatternUtils;
protected final ViewGroup mContainer;
private final FalsingManager mFalsingManager;
private final DismissCallbackRegistry mDismissCallbackRegistry;
@@ -76,6 +69,8 @@
private final BouncerExpansionCallback mExpansionCallback;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardStateController mKeyguardStateController;
+ private final KeyguardSecurityModel mKeyguardSecurityModel;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -85,32 +80,33 @@
};
private final Runnable mRemoveViewRunnable = this::removeView;
private final KeyguardBypassController mKeyguardBypassController;
- protected KeyguardHostView mKeyguardView;
+ private KeyguardHostViewController mKeyguardViewController;
private final Runnable mResetRunnable = ()-> {
- if (mKeyguardView != null) {
- mKeyguardView.resetSecurityContainer();
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.resetSecurityContainer();
}
};
private int mStatusBarHeight;
private float mExpansion = EXPANSION_HIDDEN;
protected ViewGroup mRoot;
+ private KeyguardRootViewController mRootViewController;
private boolean mShowingSoon;
private int mBouncerPromptReason;
private boolean mIsAnimatingAway;
private boolean mIsScrimmed;
- @Inject
- public KeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, @ContainerView ViewGroup container,
+ private KeyguardBouncer(Context context, ViewMediatorCallback callback,
+ ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
BouncerExpansionCallback expansionCallback,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- KeyguardBypassController keyguardBypassController, Handler handler) {
+ KeyguardBypassController keyguardBypassController, Handler handler,
+ KeyguardSecurityModel keyguardSecurityModel,
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
mContext = context;
mCallback = callback;
- mLockPatternUtils = lockPatternUtils;
mContainer = container;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mFalsingManager = falsingManager;
@@ -118,6 +114,8 @@
mExpansionCallback = expansionCallback;
mHandler = handler;
mKeyguardStateController = keyguardStateController;
+ mKeyguardSecurityModel = keyguardSecurityModel;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mKeyguardBypassController = keyguardBypassController;
}
@@ -168,7 +166,7 @@
// If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
// set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
- if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
+ if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) {
return;
}
@@ -204,12 +202,13 @@
*/
private void onFullyShown() {
mFalsingManager.onBouncerShown();
- if (mKeyguardView == null) {
+ if (mKeyguardViewController == null) {
Log.wtf(TAG, "onFullyShown when view was null");
} else {
- mKeyguardView.onResume();
+ mKeyguardViewController.onResume();
if (mRoot != null) {
- mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode());
+ mRoot.announceForAccessibility(
+ mKeyguardViewController.getAccessibilityTitleForCurrentMode());
}
}
}
@@ -233,28 +232,13 @@
showPromptReason(mBouncerPromptReason);
final CharSequence customMessage = mCallback.consumeCustomMessage();
if (customMessage != null) {
- mKeyguardView.showErrorMessage(customMessage);
+ mKeyguardViewController.showErrorMessage(customMessage);
}
- // We might still be collapsed and the view didn't have time to layout yet or still
- // be small, let's wait on the predraw to do the animation in that case.
- if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
- mKeyguardView.startAppearAnimation();
- } else {
- mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
- mKeyguardView.startAppearAnimation();
- return true;
- }
- });
- mKeyguardView.requestLayout();
- }
+ mKeyguardViewController.appear(mStatusBarHeight);
mShowingSoon = false;
if (mExpansion == EXPANSION_VISIBLE) {
- mKeyguardView.onResume();
- mKeyguardView.resetSecurityContainer();
+ mKeyguardViewController.onResume();
+ mKeyguardViewController.resetSecurityContainer();
showPromptReason(mBouncerPromptReason);
}
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
@@ -270,16 +254,16 @@
* and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
*/
public void showPromptReason(int reason) {
- if (mKeyguardView != null) {
- mKeyguardView.showPromptReason(reason);
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.showPromptReason(reason);
} else {
Log.w(TAG, "Trying to show prompt reason on empty bouncer");
}
}
public void showMessage(String message, ColorStateList colorState) {
- if (mKeyguardView != null) {
- mKeyguardView.showMessage(message, colorState);
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.showMessage(message, colorState);
} else {
Log.w(TAG, "Trying to show message on empty bouncer");
}
@@ -293,7 +277,7 @@
public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
ensureView();
- mKeyguardView.setOnDismissAction(r, cancelAction);
+ mKeyguardViewController.setOnDismissAction(r, cancelAction);
show(false /* resetSecuritySelection */);
}
@@ -307,9 +291,9 @@
mFalsingManager.onBouncerHidden();
mCallback.onBouncerVisiblityChanged(false /* shown */);
cancelShowRunnable();
- if (mKeyguardView != null) {
- mKeyguardView.cancelDismissAction();
- mKeyguardView.cleanUp();
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.cancelDismissAction();
+ mKeyguardViewController.cleanUp();
}
mIsAnimatingAway = false;
if (mRoot != null) {
@@ -328,8 +312,8 @@
*/
public void startPreHideAnimation(Runnable runnable) {
mIsAnimatingAway = true;
- if (mKeyguardView != null) {
- mKeyguardView.startDisappearAnimation(runnable);
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.startDisappearAnimation(runnable);
} else if (runnable != null) {
runnable.run();
}
@@ -345,8 +329,9 @@
}
public void onScreenTurnedOff() {
- if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
- mKeyguardView.onPause();
+ if (mKeyguardViewController != null
+ && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
+ mKeyguardViewController.onPause();
}
}
@@ -380,7 +365,7 @@
}
private void showPrimarySecurityScreen() {
- mKeyguardView.showPrimarySecurityScreen();
+ mKeyguardViewController.showPrimarySecurityScreen();
}
/**
@@ -391,10 +376,8 @@
public void setExpansion(float fraction) {
float oldExpansion = mExpansion;
mExpansion = fraction;
- if (mKeyguardView != null && !mIsAnimatingAway) {
- float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
- mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
- mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
+ if (mKeyguardViewController != null && !mIsAnimatingAway) {
+ mKeyguardViewController.setExpansion(fraction);
}
if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
@@ -405,28 +388,22 @@
mExpansionCallback.onFullyHidden();
} else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
mExpansionCallback.onStartingToHide();
- if (mKeyguardView != null) {
- mKeyguardView.onStartingToHide();
+ if (mKeyguardViewController != null) {
+ mKeyguardViewController.onStartingToHide();
}
}
}
public boolean willDismissWithAction() {
- return mKeyguardView != null && mKeyguardView.hasDismissActions();
+ return mKeyguardViewController != null && mKeyguardViewController.hasDismissActions();
}
public int getTop() {
- if (mKeyguardView == null) {
+ if (mKeyguardViewController == null) {
return 0;
}
- int top = mKeyguardView.getTop();
- // The password view has an extra top padding that should be ignored.
- if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
- View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
- top += messageArea.getTop();
- }
- return top;
+ return mKeyguardViewController.getTop();
}
protected void ensureView() {
@@ -442,10 +419,13 @@
protected void inflateView() {
removeView();
mHandler.removeCallbacks(mRemoveViewRunnable);
- mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
- mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
- mKeyguardView.setLockPatternUtils(mLockPatternUtils);
- mKeyguardView.setViewMediatorCallback(mCallback);
+ KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create();
+ mRootViewController = component.getKeyguardRootViewController();
+ mRootViewController.init();
+ mRoot = mRootViewController.getView(); // TODO(b/166448040): Don't access root view here.
+ mKeyguardViewController = component.getKeyguardHostViewController();
+ mKeyguardViewController.init();
+
mContainer.addView(mRoot, mContainer.getChildCount());
mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
com.android.systemui.R.dimen.status_bar_height);
@@ -465,7 +445,7 @@
}
public boolean onBackPressed() {
- return mKeyguardView != null && mKeyguardView.handleBackKey();
+ return mKeyguardViewController != null && mKeyguardViewController.handleBackKey();
}
/**
@@ -473,7 +453,7 @@
* notifications on Keyguard, like SIM PIN/PUK.
*/
public boolean needsFullscreenBouncer() {
- SecurityMode mode = Dependency.get(KeyguardSecurityModel.class).getSecurityMode(
+ SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
KeyguardUpdateMonitor.getCurrentUser());
return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
}
@@ -483,8 +463,8 @@
* makes this method much faster.
*/
public boolean isFullscreenBouncer() {
- if (mKeyguardView != null) {
- SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
+ if (mKeyguardViewController != null) {
+ SecurityMode mode = mKeyguardViewController.getCurrentSecurityMode();
return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
}
return false;
@@ -494,21 +474,22 @@
* WARNING: This method might cause Binder calls.
*/
public boolean isSecure() {
- return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
+ return mKeyguardSecurityModel.getSecurityMode(
+ KeyguardUpdateMonitor.getCurrentUser()) != SecurityMode.None;
}
public boolean shouldDismissOnMenuPressed() {
- return mKeyguardView.shouldEnableMenuKey();
+ return mKeyguardViewController.shouldEnableMenuKey();
}
public boolean interceptMediaKey(KeyEvent event) {
ensureView();
- return mKeyguardView.interceptMediaKey(event);
+ return mKeyguardViewController.interceptMediaKey(event);
}
public void notifyKeyguardAuthenticated(boolean strongAuth) {
ensureView();
- mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
+ mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
}
public void dump(PrintWriter pw) {
@@ -516,8 +497,8 @@
pw.println(" isShowing(): " + isShowing());
pw.println(" mStatusBarHeight: " + mStatusBarHeight);
pw.println(" mExpansion: " + mExpansion);
- pw.println(" mKeyguardView; " + mKeyguardView);
- pw.println(" mShowingSoon: " + mKeyguardView);
+ pw.println(" mKeyguardViewController; " + mKeyguardViewController);
+ pw.println(" mShowingSoon: " + mShowingSoon);
pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
}
@@ -528,4 +509,46 @@
void onStartingToShow();
void onFullyHidden();
}
+
+ /** Create a {@link KeyguardBouncer} once a container and bouncer callback are available. */
+ public static class Factory {
+ private final Context mContext;
+ private final ViewMediatorCallback mCallback;
+ private final DismissCallbackRegistry mDismissCallbackRegistry;
+ private final FalsingManager mFalsingManager;
+ private final KeyguardStateController mKeyguardStateController;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final Handler mHandler;
+ private final KeyguardSecurityModel mKeyguardSecurityModel;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+
+ @Inject
+ public Factory(Context context, ViewMediatorCallback callback,
+ DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
+ KeyguardStateController keyguardStateController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ KeyguardBypassController keyguardBypassController, Handler handler,
+ KeyguardSecurityModel keyguardSecurityModel,
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
+ mContext = context;
+ mCallback = callback;
+ mDismissCallbackRegistry = dismissCallbackRegistry;
+ mFalsingManager = falsingManager;
+ mKeyguardStateController = keyguardStateController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardBypassController = keyguardBypassController;
+ mHandler = handler;
+ mKeyguardSecurityModel = keyguardSecurityModel;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
+ }
+
+ public KeyguardBouncer create(@RootView ViewGroup container,
+ BouncerExpansionCallback expansionCallback) {
+ return new KeyguardBouncer(mContext, mCallback, container,
+ mDismissCallbackRegistry, mFalsingManager, expansionCallback,
+ mKeyguardStateController, mKeyguardUpdateMonitor, mKeyguardBypassController,
+ mHandler, mKeyguardSecurityModel, mKeyguardBouncerComponentFactory);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index b56993b..51209d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,7 +44,6 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.dagger.SysUISingleton;
@@ -104,7 +103,7 @@
private final NavigationModeController mNavigationModeController;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
- private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ private final KeyguardBouncer.Factory mKeyguardBouncerFactory;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@Override
public void onFullyShown() {
@@ -216,7 +215,7 @@
KeyguardStateController keyguardStateController,
Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
NotificationMediaManager notificationMediaManager,
- KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
+ KeyguardBouncer.Factory keyguardBouncerFactory) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -229,7 +228,7 @@
mStatusBarStateController = sysuiStatusBarStateController;
mDockManager = dockManager;
mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
- mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
+ mKeyguardBouncerFactory = keyguardBouncerFactory;
}
@Override
@@ -246,9 +245,7 @@
mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE;
}
mBiometricUnlockController = biometricUnlockController;
- mBouncer = mKeyguardBouncerComponentFactory
- .build(container, mExpansionCallback)
- .createKeyguardBouncer();
+ mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback);
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addExpansionListener(this);
mBypassController = bypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/util/ViewController.java b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
new file mode 100644
index 0000000..64f8dbb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.systemui.util;
+
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+
+/**
+ * Utility class that handles view lifecycle events for View Controllers.
+ *
+ * Implementations should handle setup and teardown related activities inside of
+ * {@link #onViewAttached()} and {@link #onViewDetached()}.
+ *
+ * @param <T> View class that this ViewController is for.
+ */
+public abstract class ViewController<T extends View> {
+ protected final T mView;
+ private boolean mInited;
+
+ private OnAttachStateChangeListener mOnAttachStateListener = new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ ViewController.this.onViewAttached();
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ ViewController.this.onViewDetached();
+ }
+ };
+
+ protected ViewController(T view) {
+ mView = view;
+ }
+
+ /** Call immediately after constructing Controller in order to handle view lifecycle events. */
+ public void init() {
+ if (mInited) {
+ return;
+ }
+ mInited = true;
+
+ if (mView.isAttachedToWindow()) {
+ mOnAttachStateListener.onViewAttachedToWindow(mView);
+ }
+ mView.addOnAttachStateChangeListener(mOnAttachStateListener);
+ }
+
+ /**
+ * Called when the view is attached and a call to {@link #init()} has been made in either order.
+ */
+ protected abstract void onViewAttached();
+
+ /**
+ * Called when the view is detached.
+ */
+ protected abstract void onViewDetached();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index c7a9af3..6f681e8 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -38,10 +38,6 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.onehanded.OneHanded;
-import com.android.systemui.onehanded.OneHandedEvents;
-import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
-import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -49,8 +45,13 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.nano.WmShellTraceProto;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedEvents;
+import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -76,6 +77,9 @@
private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional;
+ // Inject the organizer directly in case the optionals aren't loaded to depend on it. There
+ // are non-optional windowing features like FULLSCREEN.
+ private final ShellTaskOrganizer mShellTaskOrganizer;
private final ProtoTracer mProtoTracer;
@Inject
@@ -89,6 +93,7 @@
Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<OneHanded> oneHandedOptional,
+ ShellTaskOrganizer shellTaskOrganizer,
ProtoTracer protoTracer) {
super(context);
mCommandQueue = commandQueue;
@@ -101,6 +106,7 @@
mPipOptional = pipOptional;
mSplitScreenOptional = splitScreenOptional;
mOneHandedOptional = oneHandedOptional;
+ mShellTaskOrganizer = shellTaskOrganizer;
mProtoTracer = protoTracer;
mProtoTracer.add(this);
}
@@ -248,10 +254,9 @@
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis,
int backDisposition, boolean showImeSwitcher) {
- if (displayId != DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) == 0) {
- return;
+ if (displayId == DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) != 0) {
+ oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
}
- oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index adb9186..3faa8a7 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -24,7 +24,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipUiEventLogger;
@@ -36,6 +35,7 @@
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.splitscreen.SplitScreen;
import dagger.BindsOptionalOf;
@@ -96,8 +96,8 @@
@SysUISingleton
@Provides
- static ShellTaskOrganizer provideShellTaskOrganizer() {
- ShellTaskOrganizer organizer = new ShellTaskOrganizer();
+ static ShellTaskOrganizer provideShellTaskOrganizer(TransactionPool transactionPool) {
+ ShellTaskOrganizer organizer = new ShellTaskOrganizer(transactionPool);
organizer.registerOrganizer();
return organizer;
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 3a249d6..16fb2ca 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -24,8 +24,6 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.onehanded.OneHanded;
-import com.android.systemui.onehanded.OneHandedController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
@@ -40,6 +38,8 @@
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
similarity index 61%
rename from packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java
rename to packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
index dd5c833..54e879e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.keyguard;
@@ -19,11 +19,12 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import android.media.AudioManager;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
@@ -39,41 +40,44 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class KeyguardHostViewTest extends SysuiTestCase {
+public class KeyguardHostViewControllerTest extends SysuiTestCase {
@Mock
- private KeyguardSecurityContainer mSecurityContainer;
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
- private LockPatternUtils mLockPatternUtils;
+ private KeyguardHostView mKeyguardHostView;
+ @Mock
+ private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private ViewMediatorCallback mViewMediatorCallback;
+
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
- private KeyguardHostView mKeyguardHostView;
+ private KeyguardHostViewController mKeyguardHostViewController;
@Before
public void setup() {
- mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
- mKeyguardHostView = new KeyguardHostView(getContext()) {
- @Override
- protected void onFinishInflate() {
- mSecurityContainer = KeyguardHostViewTest.this.mSecurityContainer;
- mLockPatternUtils = KeyguardHostViewTest.this.mLockPatternUtils;
- }
- };
- mKeyguardHostView.onFinishInflate();
+ mKeyguardHostViewController = new KeyguardHostViewController(
+ mKeyguardHostView, mKeyguardUpdateMonitor, mKeyguardSecurityContainerController,
+ mAudioManager, mTelephonyManager, mViewMediatorCallback);
}
@Test
public void testHasDismissActions() {
- Assert.assertFalse("Action not set yet", mKeyguardHostView.hasDismissActions());
- mKeyguardHostView.setOnDismissAction(mock(OnDismissAction.class),
+ Assert.assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions());
+ mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class),
null /* cancelAction */);
- Assert.assertTrue("Action should exist", mKeyguardHostView.hasDismissActions());
+ Assert.assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions());
}
@Test
public void testOnStartingToHide() {
- mKeyguardHostView.onStartingToHide();
- verify(mSecurityContainer).onStartingToHide();
+ mKeyguardHostViewController.onStartingToHide();
+ verify(mKeyguardSecurityContainerController).onStartingToHide();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 1192023..d93cc05 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -182,7 +182,8 @@
// IBiometricsFace@1.0 does not support detection, only authentication.
when(mFaceSensorProperties.isEmpty()).thenReturn(false);
when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorProperties(0 /* id */,
- false /* supportsFaceDetection */, true /* supportsSelfIllumination */));
+ false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
+ 1 /* maxTemplatesAllowed */));
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
index 58cb032..73a7ca9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
@@ -87,6 +87,8 @@
override fun createAnimator(start: Float, end: Float) = animator
}
`when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT))).thenReturn(INITIAL_BRIGHTNESS)
+ `when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT), eq(1f)))
+ .thenReturn(INITIAL_BRIGHTNESS)
faceAuthScreenBrightnessController.attach(whiteOverlay)
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardUpdateCallback))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
deleted file mode 100644
index 41af53b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2020 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.systemui.onehanded;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.verify;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.common.DisplayController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OneHandedGestureHandlerTest extends OneHandedTestCase {
- OneHandedTouchHandler mTouchHandler;
- OneHandedTutorialHandler mTutorialHandler;
- OneHandedGestureHandler mGestureHandler;
- OneHandedController mOneHandedController;
- @Mock
- DisplayController mMockDisplayController;
- @Mock
- OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mTouchHandler = new OneHandedTouchHandler();
- mTutorialHandler = new OneHandedTutorialHandler(mContext);
- mGestureHandler = Mockito.spy(
- new OneHandedGestureHandler(mContext, mMockDisplayController));
- mOneHandedController = new OneHandedController(
- getContext(),
- mMockDisplayController,
- mMockDisplayAreaOrganizer,
- mTouchHandler,
- mTutorialHandler,
- mGestureHandler);
- mOneHandedController.setThreeButtonModeEnabled(true);
- }
-
- @Test
- public void testOneHandedManager_registerForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer, atLeastOnce())
- .registerTransitionCallback(mGestureHandler);
- }
-
- @Test
- public void testOneHandedManager_setGestureEventListener() {
- OneHandedGestureHandler.OneHandedGestureEventCallback callback =
- new OneHandedGestureHandler.OneHandedGestureEventCallback() {
- @Override
- public void onStart() {}
-
- @Override
- public void onStop() {}
- };
- mOneHandedController.registerGestureCallback(callback);
-
- verify(mGestureHandler).setGestureEventListener(callback);
- assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
- }
-
- @Test
- public void testReceiveNewConfig_whenSetOneHandedEnabled() {
- // 1st called at init
- verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
- mOneHandedController.setOneHandedEnabled(true);
- // 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
- }
-
- @Test
- public void testOneHandedDisabled_shouldDisposeInputChannel() {
- mOneHandedController.setOneHandedEnabled(false);
- mOneHandedController.setSwipeToNotificationEnabled(false);
-
- assertThat(mGestureHandler.mInputMonitor).isNull();
- assertThat(mGestureHandler.mInputEventReceiver).isNull();
- }
-
- @Test
- public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
- // 1st called at init
- verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
- mOneHandedController.setOneHandedEnabled(true);
- // 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
-
- mGestureHandler.onThreeButtonModeEnabled(false);
-
- assertThat(mGestureHandler.mInputMonitor).isNull();
- assertThat(mGestureHandler.mInputEventReceiver).isNull();
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
deleted file mode 100644
index 1e40831..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2020 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.systemui.onehanded;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.verify;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.common.DisplayController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OneHandedTouchHandlerTest extends OneHandedTestCase {
- OneHandedTouchHandler mTouchHandler;
- OneHandedTutorialHandler mTutorialHandler;
- OneHandedGestureHandler mGestureHandler;
- OneHandedController mOneHandedController;
- @Mock
- DisplayController mMockDisplayController;
- @Mock
- OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
- mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
- mOneHandedController = new OneHandedController(
- getContext(),
- mMockDisplayController,
- mMockDisplayAreaOrganizer,
- mTouchHandler,
- mTutorialHandler,
- mGestureHandler);
- }
-
- @Test
- public void testOneHandedManager_registerForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTouchHandler);
- }
-
- @Test
- public void testOneHandedManager_registerTouchEventListener() {
- verify(mTouchHandler).registerTouchEventListener(any());
- assertThat(mTouchHandler.mTouchEventCallback).isNotNull();
- }
-
- @Test
- public void testOneHandedDisabled_shouldDisposeInputChannel() {
- mOneHandedController.setOneHandedEnabled(false);
- assertThat(mTouchHandler.mInputMonitor).isNull();
- assertThat(mTouchHandler.mInputEventReceiver).isNull();
- }
-
- @Test
- public void testOneHandedEnabled_monitorInputChannel() {
- mOneHandedController.setOneHandedEnabled(true);
- assertThat(mTouchHandler.mInputMonitor).isNotNull();
- assertThat(mTouchHandler.mInputEventReceiver).isNotNull();
- }
-
- @Test
- public void testReceiveNewConfig_whenSetOneHandedEnabled() {
- // Called at init
- verify(mTouchHandler, atLeastOnce()).onOneHandedEnabled(true);
- mOneHandedController.setOneHandedEnabled(true);
- // Called by setOneHandedEnabled()
- verify(mTouchHandler, atLeast(2)).onOneHandedEnabled(true);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
index 25fb7d3..1f10d01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
@@ -32,6 +32,7 @@
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
@@ -106,6 +107,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testMicCameraChanged() {
changeMicCamera(false) // default is true
executor.runAllReady()
@@ -129,6 +131,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testBothChanged() {
changeAll(true)
changeMicCamera(false)
@@ -150,6 +153,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testMicCamera_listening() {
changeMicCamera(true)
executor.runAllReady()
@@ -158,6 +162,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testAllFalse_notListening() {
changeAll(true)
executor.runAllReady()
@@ -169,6 +174,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testSomeListening_stillListening() {
// Mic and camera are true by default
changeAll(true)
@@ -180,6 +186,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testAllDeleted_micCameraFalse_stopListening() {
changeMicCamera(false)
changeAll(true)
@@ -191,6 +198,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testMicDeleted_stillListening() {
changeMicCamera(true)
executor.runAllReady()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index f152a74..0a079b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -43,6 +43,7 @@
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
@@ -271,6 +272,7 @@
}
@Test
+ @Ignore // TODO(b/168209929)
fun testNotListeningWhenIndicatorsDisabled() {
changeAll(false)
changeMicCamera(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 8acb705..2ce22a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -58,6 +58,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.util.time.FakeSystemClock;
@@ -964,6 +965,198 @@
}
@Test
+ public void testStabilizeGroupsDoesNotAllowGrouping() {
+ // GIVEN one group child without a summary yet
+ addGroupChild(0, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // GIVEN visual stability manager doesn't allow any group changes
+ mListBuilder.setNotifStabilityManager(
+ new TestableStabilityManager().setAllowGroupChanges(false));
+
+ // WHEN we run the pipeline with the addition of a group summary & child
+ addGroupSummary(1, PACKAGE_1, GROUP_1);
+ addGroupChild(2, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // THEN all notifications are top-level and the summary doesn't show yet
+ // because group changes aren't allowed by the stability manager
+ verifyBuiltList(
+ notif(0),
+ notif(2)
+ );
+ }
+
+ @Test
+ public void testStabilizeGroupsAllowsGroupingAllNewNotifications() {
+ // GIVEN visual stability manager doesn't allow any group changes
+ mListBuilder.setNotifStabilityManager(
+ new TestableStabilityManager().setAllowGroupChanges(false));
+
+ // WHEN we run the pipeline with all new notification groups
+ addGroupChild(0, PACKAGE_1, GROUP_1);
+ addGroupSummary(1, PACKAGE_1, GROUP_1);
+ addGroupChild(2, PACKAGE_1, GROUP_1);
+ addGroupSummary(3, PACKAGE_2, GROUP_2);
+ addGroupChild(4, PACKAGE_2, GROUP_2);
+ addGroupChild(5, PACKAGE_2, GROUP_2);
+
+ dispatchBuild();
+
+ // THEN all notifications are grouped since they're all new
+ verifyBuiltList(
+ group(
+ summary(1),
+ child(0),
+ child(2)
+ ),
+ group(
+ summary(3),
+ child(4),
+ child(5)
+ )
+ );
+ }
+
+
+ @Test
+ public void testStabilizeGroupsAllowsGroupingOnlyNewNotifications() {
+ // GIVEN one group child without a summary yet
+ addGroupChild(0, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // GIVEN visual stability manager doesn't allow any group changes
+ mListBuilder.setNotifStabilityManager(
+ new TestableStabilityManager().setAllowGroupChanges(false));
+
+ // WHEN we run the pipeline with the addition of a group summary & child
+ addGroupSummary(1, PACKAGE_1, GROUP_1);
+ addGroupChild(2, PACKAGE_1, GROUP_1);
+ addGroupSummary(3, PACKAGE_2, GROUP_2);
+ addGroupChild(4, PACKAGE_2, GROUP_2);
+ addGroupChild(5, PACKAGE_2, GROUP_2);
+
+ dispatchBuild();
+
+ // THEN all notifications are top-level and the summary doesn't show yet
+ // because group changes aren't allowed by the stability manager
+ verifyBuiltList(
+ notif(0),
+ group(
+ summary(3),
+ child(4),
+ child(5)
+ ),
+ notif(2)
+ );
+ }
+
+ @Test
+ public void testStabilizeGroupsHidesGroupSummary() {
+ // GIVEN one group child with a summary
+ addGroupChild(0, PACKAGE_1, GROUP_1);
+ addGroupSummary(1, PACKAGE_1, GROUP_1);
+
+ dispatchBuild(); // group summary is hidden because it needs at least 2 children to group
+
+ // GIVEN visual stability manager doesn't allow any group changes
+ mListBuilder.setNotifStabilityManager(
+ new TestableStabilityManager().setAllowGroupChanges(false));
+
+ // WHEN we run the pipeline with the addition of a child
+ addGroupChild(2, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // THEN the children notifications are top-level and the summary still doesn't show yet
+ // because group changes aren't allowed by the stability manager
+ verifyBuiltList(
+ notif(0),
+ notif(2)
+ );
+ }
+
+ @Test
+ public void testStabilizeGroupsDelayedSummaryRendersAllNotifsTopLevel() {
+ // GIVEN group children posted without a summary
+ addGroupChild(0, PACKAGE_1, GROUP_1);
+ addGroupChild(1, PACKAGE_1, GROUP_1);
+ addGroupChild(2, PACKAGE_1, GROUP_1);
+ addGroupChild(3, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // GIVEN visual stability manager doesn't allow any group changes
+ final TestableStabilityManager stabilityManager =
+ new TestableStabilityManager().setAllowGroupChanges(false);
+ mListBuilder.setNotifStabilityManager(stabilityManager);
+
+ // WHEN the delayed summary is posted
+ addGroupSummary(4, PACKAGE_1, GROUP_1);
+
+ dispatchBuild();
+
+ // THEN all entries are top-level since group changes aren't allowed
+ verifyBuiltList(
+ notif(0),
+ notif(1),
+ notif(2),
+ notif(3),
+ notif(4)
+ );
+
+ // WHEN visual stability manager allows group changes again
+ stabilityManager.setAllowGroupChanges(true);
+ stabilityManager.invalidateList();
+
+ // THEN entries are grouped
+ verifyBuiltList(
+ group(
+ summary(4),
+ child(0),
+ child(1),
+ child(2),
+ child(3)
+ )
+ );
+ }
+
+ @Test
+ public void testStabilizeSectionDisallowsNewSection() {
+ // GIVEN one non-default sections
+ final NotifSectioner originalSectioner = new PackageSectioner(PACKAGE_1);
+ mListBuilder.setSectioners(List.of(originalSectioner));
+
+ // GIVEN notifications that's sectioned by sectioner1
+ addNotif(0, PACKAGE_1);
+ dispatchBuild();
+ assertEquals(originalSectioner, mEntrySet.get(0).getSection().getSectioner());
+
+ // WHEN section changes aren't allowed
+ final TestableStabilityManager stabilityManager =
+ new TestableStabilityManager().setAllowSectionChanges(false);
+ mListBuilder.setNotifStabilityManager(stabilityManager);
+
+ // WHEN we try to change the section
+ final NotifSectioner newSectioner = new PackageSectioner(PACKAGE_1);
+ mListBuilder.setSectioners(List.of(newSectioner, originalSectioner));
+ dispatchBuild();
+
+ // THEN the section remains the same since section changes aren't allowed
+ assertEquals(originalSectioner, mEntrySet.get(0).getSection().getSectioner());
+
+ // WHEN section changes are allowed again
+ stabilityManager.setAllowSectionChanges(true);
+ stabilityManager.invalidateList();
+
+ // THEN the section updates
+ assertEquals(newSectioner, mEntrySet.get(0).getSection().getSectioner());
+ }
+
+ @Test
public void testDispatchListOnBeforeSort() {
// GIVEN a registered OnBeforeSortListener
RecordingOnBeforeSortListener listener =
@@ -999,8 +1192,8 @@
@Test
public void testDispatchListOnBeforeRender() {
// GIVEN a registered OnBeforeRenderList
- RecordingOnBeforeRenderistener listener =
- new RecordingOnBeforeRenderistener();
+ RecordingOnBeforeRenderListener listener =
+ new RecordingOnBeforeRenderListener();
mListBuilder.addOnBeforeRenderListListener(listener);
// GIVEN some new notifs out of order
@@ -1450,7 +1643,7 @@
}
}
- private static class RecordingOnBeforeRenderistener
+ private static class RecordingOnBeforeRenderListener
implements OnBeforeRenderListListener {
List<ListEntry> mEntriesReceived;
@@ -1460,6 +1653,39 @@
}
}
+ private static class TestableStabilityManager extends NotifStabilityManager {
+ boolean mAllowGroupChanges = true;
+ boolean mAllowSectionChanges = true;
+
+ TestableStabilityManager() {
+ super("Test");
+ }
+
+ TestableStabilityManager setAllowGroupChanges(boolean allowGroupChanges) {
+ mAllowGroupChanges = allowGroupChanges;
+ return this;
+ }
+
+ TestableStabilityManager setAllowSectionChanges(boolean allowSectionChanges) {
+ mAllowSectionChanges = allowSectionChanges;
+ return this;
+ }
+
+ @Override
+ public void onBeginRun() {
+ }
+
+ @Override
+ public boolean isGroupChangeAllowed(NotificationEntry entry) {
+ return mAllowGroupChanges;
+ }
+
+ @Override
+ public boolean isSectionChangeAllowed(NotificationEntry entry) {
+ return mAllowSectionChanges;
+ }
+ }
+
private static final String PACKAGE_1 = "com.test1";
private static final String PACKAGE_2 = "com.test2";
private static final String PACKAGE_3 = "org.test3";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index 09c9bcd..711f0ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
import org.junit.Assert.assertFalse
@@ -47,12 +48,10 @@
private lateinit var promoter: NotifPromoter
private lateinit var peopleSectioner: NotifSectioner
- @Mock
- private lateinit var pipeline: NotifPipeline
- @Mock
- private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier
- @Mock
- private lateinit var channel: NotificationChannel
+ @Mock private lateinit var pipeline: NotifPipeline
+ @Mock private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier
+ @Mock private lateinit var channel: NotificationChannel
+ @Mock private lateinit var headerController: NodeController
private lateinit var entry: NotificationEntry
private lateinit var coordinator: ConversationCoordinator
@@ -60,7 +59,7 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- coordinator = ConversationCoordinator(peopleNotificationIdentifier)
+ coordinator = ConversationCoordinator(peopleNotificationIdentifier, headerController)
whenever(channel.isImportantConversation).thenReturn(true)
coordinator.attach(pipeline)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
index fa992a5..7e771ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
@@ -73,6 +74,7 @@
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
@Mock private NotifLifetimeExtender.OnEndLifetimeExtensionCallback mEndLifetimeExtension;
+ @Mock private NodeController mHeaderController;
private NotificationEntry mEntry;
@@ -85,8 +87,8 @@
mHeadsUpManager,
mHeadsUpViewBinder,
mNotificationInterruptStateProvider,
- mRemoteInputManager
- );
+ mRemoteInputManager,
+ mHeaderController);
mCoordinator.attach(mNotifPipeline);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index 3a7d28a..1031d6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -38,6 +38,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.NodeController;
import org.junit.Before;
import org.junit.Test;
@@ -54,6 +55,8 @@
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private HighPriorityProvider mHighPriorityProvider;
@Mock private NotifPipeline mNotifPipeline;
+ @Mock private NodeController mAlertingHeaderController;
+ @Mock private NodeController mSilentHeaderController;
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
@@ -67,8 +70,9 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- RankingCoordinator rankingCoordinator =
- new RankingCoordinator(mStatusBarStateController, mHighPriorityProvider);
+ RankingCoordinator rankingCoordinator = new RankingCoordinator(
+ mStatusBarStateController, mHighPriorityProvider, mAlertingHeaderController,
+ mSilentHeaderController);
mEntry = new NotificationEntryBuilder().build();
rankingCoordinator.attach(mNotifPipeline);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 605b4d1..4edca7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -296,6 +296,22 @@
}
@Test
+ public void testNotSuppressingGroupChangesAnymore_invalidationCalled() {
+ // GIVEN visual stability is being maintained b/c panel is expanded
+ setPulsing(false);
+ setScreenOn(true);
+ setPanelExpanded(true);
+
+ assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
+
+ // WHEN the panel isn't expanded anymore
+ setPanelExpanded(false);
+
+ // invalidate is called because we were previously suppressing a group change
+ verifyInvalidateCalled(true);
+ }
+
+ @Test
public void testHeadsUp_allowedToChangeGroupAndSection() {
// GIVEN group + section changes disallowed
setScreenOn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 7ca2478..8cd7103 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -63,6 +64,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -87,6 +89,10 @@
@Mock private NotificationRowComponent mNotificationRowComponent;
@Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
@Mock private NotificationSectionsLogger mLogger;
+ @Mock private SectionHeaderController mIncomingHeaderController;
+ @Mock private SectionHeaderController mPeopleHeaderController;
+ @Mock private SectionHeaderController mAlertingHeaderController;
+ @Mock private SectionHeaderController mSilentHeaderController;
private NotificationSectionsManager mSectionsManager;
@@ -109,15 +115,21 @@
});
when(mNotificationRowComponent.getActivatableNotificationViewController())
.thenReturn(mActivatableNotificationViewController);
+ when(mIncomingHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
+ when(mPeopleHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
+ when(mAlertingHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
+ when(mSilentHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
mSectionsManager =
new NotificationSectionsManager(
- mActivityStarterDelegate,
mStatusBarStateController,
mConfigurationController,
- mPeopleHubAdapter,
mKeyguardMediaController,
mSectionsFeatureManager,
- mLogger
+ mLogger,
+ mIncomingHeaderController,
+ mPeopleHeaderController,
+ mAlertingHeaderController,
+ mSilentHeaderController
);
// Required in order for the header inflation to work properly
when(mNssl.generateLayoutParams(any(AttributeSet.class)))
@@ -241,8 +253,9 @@
mSectionsManager.updateSectionBoundaries();
clearInvocations(mNssl);
+ SectionHeaderView silentHeaderView = mSectionsManager.getSilentHeaderView();
ViewGroup transientParent = mock(ViewGroup.class);
- mSectionsManager.getSilentHeaderView().setTransientContainer(transientParent);
+ when(silentHeaderView.getTransientContainer()).thenReturn(transientParent);
// WHEN the LO section reappears
setStackState(
@@ -252,8 +265,8 @@
// THEN the header is first removed from the transient parent before being added to the
// NSSL.
- verify(transientParent).removeTransientView(mSectionsManager.getSilentHeaderView());
- verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 1);
+ verify(transientParent).removeTransientView(silentHeaderView);
+ verify(mNssl).addView(silentHeaderView, 1);
}
@Test
@@ -358,23 +371,6 @@
}
@Test
- public void testPeopleFiltering_keepPeopleHeaderWhenSectionEmpty() {
- mSectionsManager.setPeopleHubVisible(true);
- enablePeopleFiltering();
-
- setStackState(
- PEOPLE_HEADER,
- ALERTING_HEADER,
- ALERTING,
- GENTLE_HEADER,
- GENTLE);
- mSectionsManager.updateSectionBoundaries();
-
- verify(mNssl, never()).removeView(mSectionsManager.getPeopleHeaderView());
- verify(mNssl).changeViewPosition(mSectionsManager.getPeopleHeaderView(), 0);
- }
-
- @Test
public void testPeopleFiltering_AlertingHunWhilePeopleVisible() {
enablePeopleFiltering();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index de59ac31..81cbef7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -16,6 +16,8 @@
import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@@ -43,44 +45,26 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
-import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.util.leak.LeakDetector;
import org.junit.After;
import org.junit.Before;
@@ -92,9 +76,6 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Tests for {@link NotificationStackScrollLayout}.
*/
@@ -109,7 +90,6 @@
@Rule public MockitoRule mockito = MockitoJUnit.rule();
@Mock private StatusBar mBar;
@Mock private SysuiStatusBarStateController mBarState;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationBlockingHelperManager mBlockingHelperManager;
@Mock private NotificationGroupManagerLegacy mGroupMembershipManger;
@Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@@ -122,11 +102,9 @@
@Mock private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
@Mock private NotificationSectionsManager mNotificationSectionsManager;
@Mock private NotificationSection mNotificationSection;
- @Mock private FeatureFlags mFeatureFlags;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
- @Mock NotificationStackScrollLayoutController mStackScrollLayoutController;
- private NotificationEntryManager mEntryManager;
+ @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
private int mOriginalInterruptionModelSetting;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -154,31 +132,6 @@
mRemoteInputManager);
mDependency.injectMockDependency(ShadeController.class);
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-
- mEntryManager = new NotificationEntryManager(
- mock(NotificationEntryManagerLogger.class),
- mock(NotificationGroupManagerLegacy.class),
- new NotificationRankingManager(
- () -> mock(NotificationMediaManager.class),
- mGroupMembershipManger,
- mHeadsUpManager,
- mock(NotificationFilter.class),
- mock(NotificationEntryManagerLogger.class),
- mock(NotificationSectionsFeatureManager.class),
- mock(PeopleNotificationIdentifier.class),
- mock(HighPriorityProvider.class)
- ),
- mock(NotificationEntryManager.KeyguardEnvironment.class),
- mock(FeatureFlags.class),
- () -> mock(NotificationRowBinder.class),
- () -> mRemoteInputManager,
- mock(LeakDetector.class),
- mock(ForegroundServiceDismissalFeatureController.class),
- mock(IStatusBarService.class)
- );
- mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class));
- when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
-
NotificationShelfController notificationShelfController =
mock(NotificationShelfController.class);
NotificationShelf notificationShelf = mock(NotificationShelf.class);
@@ -196,18 +149,13 @@
getContext(),
null,
mNotificationRoundnessManager,
- mock(DynamicPrivacyController.class),
mStatusBarStateController,
mNotificationSectionsManager,
mock(ForegroundServiceSectionController.class),
mock(ForegroundServiceDismissalFeatureController.class),
- mFeatureFlags,
- mock(NotifPipeline.class),
- mEntryManager,
- mock(NotifCollection.class),
- mUiEventLoggerFake,
mGroupMembershipManger,
- mGroupExpansionManager
+ mGroupExpansionManager,
+ mUiEventLoggerFake
);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper);
@@ -216,9 +164,9 @@
mStackScroller.setStatusBar(mBar);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mStackScrollLayoutController.getNoticationRoundessManager())
- .thenReturn(mock(NotificationRoundnessManager.class));
+ .thenReturn(mNotificationRoundnessManager);
mStackScroller.setController(mStackScrollLayoutController);
-
+
// Stub out functionality that isn't necessary to test.
doNothing().when(mBar)
.executeRunnableDismissingKeyguard(any(Runnable.class),
@@ -323,8 +271,6 @@
@Test
public void testUpdateFooter_noNotifications() {
setBarStateForTest(StatusBarState.SHADE);
- assertEquals(0, mEntryManager.getActiveNotificationsCount());
-
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
mStackScroller.updateFooter();
@@ -334,15 +280,15 @@
@Test
public void testUpdateFooter_remoteInput() {
setBarStateForTest(StatusBarState.SHADE);
- ArrayList<NotificationEntry> entries = new ArrayList<>();
- entries.add(new NotificationEntryBuilder().build());
- addEntriesToEntryManager(entries);
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
when(row.canViewBeDismissed()).thenReturn(true);
when(mStackScroller.getChildCount()).thenReturn(1);
when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
when(mRemoteInputController.isRemoteInputActive()).thenReturn(true);
+ when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+ .thenReturn(true);
+ when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
@@ -354,14 +300,9 @@
public void testUpdateFooter_oneClearableNotification() {
setBarStateForTest(StatusBarState.SHADE);
- ArrayList<NotificationEntry> entries = new ArrayList<>();
- entries.add(new NotificationEntryBuilder().build());
- addEntriesToEntryManager(entries);
-
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
- when(row.canViewBeDismissed()).thenReturn(true);
- when(mStackScroller.getChildCount()).thenReturn(1);
- when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
+ when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+ .thenReturn(true);
+ when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
@@ -373,9 +314,13 @@
public void testUpdateFooter_oneNonClearableNotification() {
setBarStateForTest(StatusBarState.SHADE);
- ArrayList<NotificationEntry> entries = new ArrayList<>();
- entries.add(new NotificationEntryBuilder().build());
- addEntriesToEntryManager(entries);
+ ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+ when(row.canViewBeDismissed()).thenReturn(false);
+ when(mStackScroller.getChildCount()).thenReturn(1);
+ when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
+ when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
+ when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+ .thenReturn(false);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
@@ -435,7 +380,7 @@
@Test
public void testClearNotifications_All() {
- mStackScroller.clearNotifications(NotificationStackScrollLayout.ROWS_ALL, true);
+ mStackScroller.clearNotifications(ROWS_ALL, true);
assertEquals(1, mUiEventLoggerFake.numLogs());
assertEquals(NotificationStackScrollLayout.NotificationPanelEvent
.DISMISS_ALL_NOTIFICATIONS_PANEL.getId(), mUiEventLoggerFake.eventId(0));
@@ -508,10 +453,4 @@
// rather than the mock because the spy just coppied the anonymous inner /shruggie.
mStackScroller.setStatusBarState(state);
}
-
- private void addEntriesToEntryManager(List<NotificationEntry> entries) {
- for (NotificationEntry e : entries) {
- mEntryManager.addActiveNotificationForTest(e);
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
index 32c6828..60d6c53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
@@ -37,6 +37,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.media.KeyguardMediaController;
@@ -44,11 +45,16 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
@@ -76,53 +82,38 @@
@RunWith(AndroidTestingRunner.class)
public class NotificationStackScrollerControllerTest extends SysuiTestCase {
- @Mock
- private NotificationGutsManager mNotificationGutsManager;
- @Mock
- private HeadsUpManagerPhone mHeadsUpManager;
- @Mock
- private NotificationRoundnessManager mNotificationRoundnessManager;
- @Mock
- private TunerService mTunerService;
- @Mock
- private DynamicPrivacyController mDynamicPrivacyController;
- @Mock
- private ConfigurationController mConfigurationController;
- @Mock
- private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock
- private ZenModeController mZenModeController;
- @Mock
- private KeyguardMediaController mKeyguardMediaController;
- @Mock
- private SysuiStatusBarStateController mSysuiStatusBarStateController;
- @Mock
- private KeyguardBypassController mKeyguardBypassController;
- @Mock
- private SysuiColorExtractor mColorExtractor;
- @Mock
- private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
- @Mock
- private MetricsLogger mMetricsLogger;
- @Mock
- private FalsingManager mFalsingManager;
- @Mock
- private NotificationSectionsManager mNotificationSectionsManager;
- @Mock
- private Resources mResources;
+ @Mock private NotificationGutsManager mNotificationGutsManager;
+ @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private NotificationRoundnessManager mNotificationRoundnessManager;
+ @Mock private TunerService mTunerService;
+ @Mock private DynamicPrivacyController mDynamicPrivacyController;
+ @Mock private ConfigurationController mConfigurationController;
+ @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
+ @Mock private ZenModeController mZenModeController;
+ @Mock private KeyguardMediaController mKeyguardMediaController;
+ @Mock private SysuiStatusBarStateController mSysuiStatusBarStateController;
+ @Mock private KeyguardBypassController mKeyguardBypassController;
+ @Mock private SysuiColorExtractor mColorExtractor;
+ @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
+ @Mock private MetricsLogger mMetricsLogger;
+ @Mock private FalsingManager mFalsingManager;
+ @Mock private NotificationSectionsManager mNotificationSectionsManager;
+ @Mock private Resources mResources;
@Mock(answer = Answers.RETURNS_SELF)
private NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
- @Mock
- private NotificationSwipeHelper mNotificationSwipeHelper;
- @Mock
- private StatusBar mStatusBar;
- @Mock
- private ScrimController mScrimController;
- @Mock
- private NotificationGroupManagerLegacy mLegacyGroupManager;
+ @Mock private NotificationSwipeHelper mNotificationSwipeHelper;
+ @Mock private StatusBar mStatusBar;
+ @Mock private ScrimController mScrimController;
+ @Mock private NotificationGroupManagerLegacy mLegacyGroupManager;
+ @Mock private SectionHeaderController mSilentHeaderController;
+ @Mock private FeatureFlags mFeatureFlags;
+ @Mock private NotifPipeline mNotifPipeline;
+ @Mock private NotifCollection mNotifCollection;
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private IStatusBarService mIStatusBarService;
@Captor
- ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
+ private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
private NotificationStackScrollLayoutController mController;
@@ -131,6 +122,7 @@
MockitoAnnotations.initMocks(this);
when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper);
+ when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mController = new NotificationStackScrollLayoutController(
true,
@@ -154,7 +146,13 @@
mStatusBar,
mScrimController,
mLegacyGroupManager,
- mLegacyGroupManager
+ mLegacyGroupManager,
+ mSilentHeaderController,
+ mFeatureFlags,
+ mNotifPipeline,
+ mNotifCollection,
+ mEntryManager,
+ mIStatusBarService
);
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
@@ -254,7 +252,6 @@
UserChangedListener changedListener = userChangedCaptor.getValue();
changedListener.onUserChanged(0);
- verify(mNotificationStackScrollLayout).setCurrentUserid(0);
verify(mNotificationStackScrollLayout).updateSensitiveness(false, true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 0a041e4..1b05ad7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -38,16 +38,16 @@
import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardHostViewController;
+import com.android.keyguard.KeyguardRootViewController;
import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -76,13 +76,9 @@
@Mock
private ViewMediatorCallback mViewMediatorCallback;
@Mock
- private LockPatternUtils mLockPatternUtils;
- @Mock
private DismissCallbackRegistry mDismissCallbackRegistry;
@Mock
- private KeyguardHostView mKeyguardHostView;
- @Mock
- private ViewTreeObserver mViewTreeObserver;
+ private KeyguardHostViewController mKeyguardHostViewController;
@Mock
private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback;
@Mock
@@ -96,7 +92,13 @@
@Mock
private KeyguardSecurityModel mKeyguardSecurityModel;
@Mock
+ private KeyguardRootViewController mRootViewController;
+ @Mock
private ViewGroup mRootView;
+ @Mock
+ private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ @Mock
+ private KeyguardBouncerComponent mKeyguardBouncerComponent;
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
private Integer mRootVisibility = View.INVISIBLE;
@@ -106,7 +108,6 @@
public void setup() {
allowTestableLooperAsMainThread();
mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
- mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
mDependency.injectMockDependency(KeyguardStateController.class);
when(mRootView.getVisibility()).thenAnswer((Answer<Integer>) invocation -> mRootVisibility);
doAnswer(invocation -> {
@@ -116,19 +117,22 @@
when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
.thenReturn(KeyguardSecurityModel.SecurityMode.None);
DejankUtils.setImmediate(true);
+ when(mKeyguardBouncerComponentFactory.create()).thenReturn(mKeyguardBouncerComponent);
+ when(mKeyguardBouncerComponent.getKeyguardHostViewController())
+ .thenReturn(mKeyguardHostViewController);
+ when(mKeyguardBouncerComponent.getKeyguardRootViewController())
+ .thenReturn(mRootViewController);
+
+ when(mRootViewController.getView()).thenReturn(mRootView);
+ when(mRootView.getResources()).thenReturn(mContext.getResources());
+
final ViewGroup container = new FrameLayout(getContext());
- when(mKeyguardHostView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
- when(mKeyguardHostView.getHeight()).thenReturn(500);
- mBouncer = new KeyguardBouncer(getContext(), mViewMediatorCallback,
- mLockPatternUtils, container, mDismissCallbackRegistry, mFalsingManager,
- mExpansionCallback, mKeyguardStateController, mKeyguardUpdateMonitor,
- mKeyguardBypassController, mHandler) {
- @Override
- protected void inflateView() {
- mKeyguardView = mKeyguardHostView;
- mRoot = mRootView;
- }
- };
+ mBouncer = new KeyguardBouncer.Factory(getContext(), mViewMediatorCallback,
+ mDismissCallbackRegistry, mFalsingManager,
+ mKeyguardStateController, mKeyguardUpdateMonitor,
+ mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
+ mKeyguardBouncerComponentFactory)
+ .create(container, mExpansionCallback);
}
@Test
@@ -154,12 +158,10 @@
mBouncer.ensureView();
mBouncer.setExpansion(1);
- reset(mKeyguardHostView);
- when(mKeyguardHostView.getHeight()).thenReturn(500);
+ reset(mKeyguardHostViewController);
mBouncer.show(true);
- verify(mKeyguardHostView).setAlpha(eq(1f));
- verify(mKeyguardHostView).setTranslationY(eq(0f));
+ verify(mKeyguardHostViewController).setExpansion(0);
}
@Test
@@ -177,23 +179,23 @@
@Test
public void testShow_triesToDismissKeyguard() {
mBouncer.show(true);
- verify(mKeyguardHostView).dismiss(anyInt());
+ verify(mKeyguardHostViewController).dismiss(anyInt());
}
@Test
public void testShow_resetsSecuritySelection() {
mBouncer.show(false);
- verify(mKeyguardHostView, never()).showPrimarySecurityScreen();
+ verify(mKeyguardHostViewController, never()).showPrimarySecurityScreen();
mBouncer.hide(false);
mBouncer.show(true);
- verify(mKeyguardHostView).showPrimarySecurityScreen();
+ verify(mKeyguardHostViewController).showPrimarySecurityScreen();
}
@Test
public void testShow_animatesKeyguardView() {
mBouncer.show(true);
- verify(mKeyguardHostView).startAppearAnimation();
+ verify(mKeyguardHostViewController).appear(anyInt());
}
@Test
@@ -201,7 +203,7 @@
final String errorMessage = "an error message";
when(mViewMediatorCallback.consumeCustomMessage()).thenReturn(errorMessage);
mBouncer.show(true);
- verify(mKeyguardHostView).showErrorMessage(eq(errorMessage));
+ verify(mKeyguardHostViewController).showErrorMessage(eq(errorMessage));
}
@Test
@@ -218,10 +220,10 @@
verify(mExpansionCallback).onFullyShown();
verify(mExpansionCallback, never()).onStartingToHide();
- verify(mKeyguardHostView, never()).onStartingToHide();
+ verify(mKeyguardHostViewController, never()).onStartingToHide();
mBouncer.setExpansion(0.9f);
verify(mExpansionCallback).onStartingToHide();
- verify(mKeyguardHostView).onStartingToHide();
+ verify(mKeyguardHostViewController).onStartingToHide();
}
@Test
@@ -230,7 +232,7 @@
mBouncer.setExpansion(0.1f);
mBouncer.setExpansion(0);
- verify(mKeyguardHostView).onResume();
+ verify(mKeyguardHostViewController).onResume();
verify(mRootView).announceForAccessibility(any());
}
@@ -267,7 +269,7 @@
public void testShowPromptReason_propagates() {
mBouncer.ensureView();
mBouncer.showPromptReason(1);
- verify(mKeyguardHostView).showPromptReason(eq(1));
+ verify(mKeyguardHostViewController).showPromptReason(eq(1));
}
@Test
@@ -275,7 +277,8 @@
final String message = "a message";
mBouncer.ensureView();
mBouncer.showMessage(message, ColorStateList.valueOf(Color.GREEN));
- verify(mKeyguardHostView).showMessage(eq(message), eq(ColorStateList.valueOf(Color.GREEN)));
+ verify(mKeyguardHostViewController).showMessage(
+ eq(message), eq(ColorStateList.valueOf(Color.GREEN)));
}
@Test
@@ -283,7 +286,7 @@
final OnDismissAction dismissAction = () -> false;
final Runnable cancelAction = () -> {};
mBouncer.showWithDismissAction(dismissAction, cancelAction);
- verify(mKeyguardHostView).setOnDismissAction(dismissAction, cancelAction);
+ verify(mKeyguardHostViewController).setOnDismissAction(dismissAction, cancelAction);
Assert.assertTrue("Should be showing", mBouncer.isShowing());
}
@@ -297,7 +300,7 @@
ran[0] = false;
mBouncer.ensureView();
mBouncer.startPreHideAnimation(r);
- verify(mKeyguardHostView).startDisappearAnimation(r);
+ verify(mKeyguardHostViewController).startDisappearAnimation(r);
Assert.assertFalse("Callback should have been deferred", ran[0]);
}
@@ -322,16 +325,14 @@
public void testSetExpansion() {
mBouncer.ensureView();
mBouncer.setExpansion(0.5f);
- verify(mKeyguardHostView).setAlpha(anyFloat());
- verify(mKeyguardHostView).setTranslationY(anyFloat());
+ verify(mKeyguardHostViewController).setExpansion(0.5f);
}
@Test
public void testIsFullscreenBouncer_asksKeyguardView() {
mBouncer.ensureView();
mBouncer.isFullscreenBouncer();
- verify(mKeyguardHostView).getCurrentSecurityMode();
- verify(mKeyguardHostView, never()).getSecurityMode();
+ verify(mKeyguardHostViewController).getCurrentSecurityMode();
}
@Test
@@ -346,21 +347,18 @@
@Test
public void testIsHiding_skipsTranslation() {
mBouncer.show(false /* reset */);
- reset(mKeyguardHostView);
+ reset(mKeyguardHostViewController);
mBouncer.startPreHideAnimation(null /* runnable */);
mBouncer.setExpansion(0.5f);
- verify(mKeyguardHostView, never()).setTranslationY(anyFloat());
- verify(mKeyguardHostView, never()).setAlpha(anyFloat());
+ verify(mKeyguardHostViewController, never()).setExpansion(anyFloat());
}
@Test
public void testIsSecure() {
- Assert.assertTrue("Bouncer is secure before inflating views", mBouncer.isSecure());
-
mBouncer.ensureView();
for (KeyguardSecurityModel.SecurityMode mode : KeyguardSecurityModel.SecurityMode.values()){
- reset(mKeyguardHostView);
- when(mKeyguardHostView.getSecurityMode()).thenReturn(mode);
+ reset(mKeyguardSecurityModel);
+ when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(mode);
Assert.assertEquals("Security doesn't match for mode: " + mode,
mBouncer.isSecure(), mode != KeyguardSecurityModel.SecurityMode.None);
}
@@ -392,7 +390,7 @@
public void testWillDismissWithAction() {
mBouncer.ensureView();
Assert.assertFalse("Action not set yet", mBouncer.willDismissWithAction());
- when(mKeyguardHostView.hasDismissActions()).thenReturn(true);
+ when(mKeyguardHostViewController.hasDismissActions()).thenReturn(true);
Assert.assertTrue("Action should exist", mBouncer.willDismissWithAction());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 1083273..9832d31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -39,7 +39,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -92,9 +91,7 @@
@Mock
private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController;
@Mock
- private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
- @Mock
- private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ private KeyguardBouncer.Factory mKeyguardBouncerFactory;
@Mock
private KeyguardBouncer mBouncer;
@@ -107,11 +104,10 @@
when(mLockIconContainer.animate()).thenReturn(mock(ViewPropertyAnimator.class,
RETURNS_DEEP_STUBS));
- when(mKeyguardBouncerComponentFactory.build(
+ when(mKeyguardBouncerFactory.create(
any(ViewGroup.class),
any(KeyguardBouncer.BouncerExpansionCallback.class)))
- .thenReturn(mKeyguardBouncerComponent);
- when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+ .thenReturn(mBouncer);
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(
getContext(),
@@ -126,7 +122,7 @@
mKeyguardStateController,
Optional.of(mFaceAuthScreenBrightnessController),
mock(NotificationMediaManager.class),
- mKeyguardBouncerComponentFactory);
+ mKeyguardBouncerFactory);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
mNotificationPanelView, mBiometrucUnlockController,
mLockIconContainer, mNotificationContainer, mBypassController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 51cc5f1..94d5458 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -30,15 +30,16 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.onehanded.OneHanded;
-import com.android.systemui.onehanded.OneHandedGestureHandler;
-import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.onehanded.OneHandedGestureHandler;
+import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
@@ -64,6 +65,7 @@
@Mock Pip mPip;
@Mock SplitScreen mSplitScreen;
@Mock OneHanded mOneHanded;
+ @Mock ShellTaskOrganizer mTaskOrganizer;
@Mock ProtoTracer mProtoTracer;
@Before
@@ -72,7 +74,7 @@
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
- Optional.of(mOneHanded), mProtoTracer);
+ Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
}
@Test
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..e66d920
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.5,10.25c0-2.79-1.22-5.43-3.35-7.24c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06 C18.97,5.68,20,7.9,20,10.25c0,0.41,0.34,0.75,0.75,0.75S21.5,10.66,21.5,10.25z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2.5c-0.83,0-1.5,0.67-1.5,1.5v0.7C7.91,5.36,6,7.71,6,10.5V15c0,0.55-0.45,1-1,1s-1,0.45-1,1v2h16v-2 c0-0.55-0.45-1-1-1s-1-0.45-1-1v-4.5c0-2.79-1.91-5.14-4.5-5.8V4C13.5,3.17,12.83,2.5,12,2.5z M16.5,10.5V15 c0,1.21,0.86,2.22,2,2.45v0.05h-13v-0.05c1.14-0.23,2-1.24,2-2.45v-4.5C7.5,8.02,9.52,6,12,6S16.5,8.02,16.5,10.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..2f5bdb0e
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4.12,9.67C4.42,7.73,5.38,6,6.77,4.73C7.19,4.35,7.2,3.7,6.8,3.3c-0.39-0.39-1-0.39-1.4-0.03 C3.7,4.84,2.52,6.96,2.15,9.34c-0.1,0.61,0.37,1.16,0.99,1.16C3.63,10.5,4.04,10.15,4.12,9.67z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.6,3.28c-0.4-0.37-1.02-0.36-1.4,0.02c-0.4,0.4-0.38,1.04,0.03,1.42c1.38,1.27,2.35,3,2.65,4.94 c0.08,0.49,0.5,0.84,0.98,0.84c0.61,0,1.09-0.55,0.99-1.16C21.47,6.96,20.29,4.84,18.6,3.28z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,16v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5S10.5,3.17,10.5,4v0.68C7.63,5.36,6,7.92,6,11v5 l-2.15,2.15c-0.19,0.2-0.19,0.51,0.01,0.71C3.95,18.95,4.07,19,4.2,19h15.6c0.45,0,0.67-0.54,0.35-0.85L18,16z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..c92bdf6
--- /dev/null
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6.81,3.81L5.75,2.75C3.45,4.76,2,7.71,2,11h1.5C3.5,8.13,4.79,5.55,6.81,3.81z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M18.25,2.75l-1.06,1.06C19.21,5.55,20.5,8.13,20.5,11H22C22,7.71,20.55,4.76,18.25,2.75z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M18,10.5c0-4.38-2.72-5.57-4.5-5.89V4c0-1.59-1.43-1.5-1.5-1.5c-0.05,0-1.5-0.09-1.5,1.5v0.62C8.72,4.94,6,6.14,6,10.5v7 H4V19h16v-1.5h-2V10.5z M16.5,17.5h-9v-7C7.5,7.57,8.94,5.95,12,6c3.07-0.05,4.5,1.55,4.5,4.5V17.5z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M12,22c0.07,0,2,0.12,2-2h-4C10,22.12,11.91,22,12,22z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..8f854e7
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2.5c-0.69,0-1.25,0.56-1.25,1.25v0.77C8.04,5.11,6,7.51,6,10.4V17H4.75C4.34,17,4,17.34,4,17.75s0.34,0.75,0.75,0.75 h14.5c0.41,0,0.75-0.34,0.75-0.75S19.66,17,19.25,17H18v-6.6c0-2.88-2.04-5.29-4.75-5.87V3.75C13.25,3.06,12.69,2.5,12,2.5z M16.5,10.4V17h-9v-6.6c0-2.48,2.02-4.5,4.5-4.5S16.5,7.91,16.5,10.4z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.15,3.01c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06C18.97,5.68,20,7.9,20,10.25 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75C21.5,7.46,20.28,4.82,18.15,3.01z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..e022c63
--- /dev/null
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M6.47,4.81c0.37-0.38,0.35-0.99-0.03-1.37c-0.4-0.4-1.05-0.39-1.44,0.02c-1.62,1.72-2.7,3.95-2.95,6.43 C2,10.48,2.46,11,3.05,11h0.01c0.51,0,0.93-0.38,0.98-0.88C4.24,8.07,5.13,6.22,6.47,4.81z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M18.99,3.47c-0.39-0.41-1.04-0.42-1.44-0.02c-0.38,0.38-0.39,0.98-0.03,1.37c1.34,1.41,2.23,3.26,2.43,5.3 c0.05,0.5,0.48,0.88,0.98,0.88h0.01c0.59,0,1.05-0.52,0.99-1.11C21.69,7.42,20.61,5.19,18.99,3.47z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M19,17h-1v-6c0-3.07-1.63-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5c-0.83,0-1.5,0.67-1.5,1.5v0.68C7.64,5.36,6,7.92,6,11 v6H5c-0.55,0-1,0.45-1,1c0,0.55,0.45,1,1,1h14c0.55,0,1-0.45,1-1C20,17.45,19.55,17,19,17z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..1e25d27
--- /dev/null
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M18,6.5L16.5,5H13V3h-2v2H7.5L6,6.5v11H4V19h16v-1.5h-2V6.5z M7.5,17.5v-11h9v11H7.5z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M6.81,3.81L5.75,2.75C3.45,4.76,2,7.71,2,11h1.5C3.5,8.13,4.79,5.55,6.81,3.81z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M18.25,2.75l-1.06,1.06C19.21,5.55,20.5,8.13,20.5,11H22C22,7.71,20.55,4.76,18.25,2.75z"/>
+</vector>
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 3d6a128..4473754 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -72,7 +72,8 @@
};
/**
- * Register a UiAutomation. Only one may be registered at a time.
+ * Register a UiAutomation if it uses the accessibility subsystem. Only one may be registered
+ * at a time.
*
* @param owner A binder object owned by the process that owns the UiAutomation to be
* registered.
@@ -80,6 +81,7 @@
* @param accessibilityServiceInfo The UiAutomation's service info
* @param flags The UiAutomation's flags
* @param id The id for the service connection
+ * @see UiAutomation#FLAG_DONT_USE_ACCESSIBILITY
*/
void registerUiTestAutomationServiceLocked(IBinder owner,
IAccessibilityServiceClient serviceClient,
@@ -88,14 +90,15 @@
AccessibilitySecurityPolicy securityPolicy,
AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
WindowManagerInternal windowManagerInternal,
- SystemActionPerformer systemActionPerfomer,
+ SystemActionPerformer systemActionPerformer,
AccessibilityWindowManager awm, int flags) {
synchronized (mLock) {
accessibilityServiceInfo.setComponentName(COMPONENT_NAME);
if (mUiAutomationService != null) {
- throw new IllegalStateException("UiAutomationService " + serviceClient
- + "already registered!");
+ throw new IllegalStateException(
+ "UiAutomationService " + mUiAutomationService.mServiceInterface
+ + "already registered!");
}
try {
@@ -106,12 +109,17 @@
return;
}
+ mUiAutomationFlags = flags;
mSystemSupport = systemSupport;
+ // Ignore registering UiAutomation if it is not allowed to use the accessibility
+ // subsystem.
+ if (!useAccessibility()) {
+ return;
+ }
mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id,
mainHandler, mLock, securityPolicy, systemSupport, windowManagerInternal,
- systemActionPerfomer, awm);
+ systemActionPerformer, awm);
mUiAutomationServiceOwner = owner;
- mUiAutomationFlags = flags;
mUiAutomationServiceInfo = accessibilityServiceInfo;
mUiAutomationService.mServiceInterface = serviceClient;
mUiAutomationService.onAdded();
@@ -130,15 +138,15 @@
void unregisterUiTestAutomationServiceLocked(IAccessibilityServiceClient serviceClient) {
synchronized (mLock) {
- if ((mUiAutomationService == null)
+ if (useAccessibility()
+ && ((mUiAutomationService == null)
|| (serviceClient == null)
|| (mUiAutomationService.mServiceInterface == null)
|| (serviceClient.asBinder()
- != mUiAutomationService.mServiceInterface.asBinder())) {
+ != mUiAutomationService.mServiceInterface.asBinder()))) {
throw new IllegalStateException("UiAutomationService " + serviceClient
+ " not registered!");
}
-
destroyUiAutomationService();
}
}
@@ -150,14 +158,19 @@
}
boolean isUiAutomationRunningLocked() {
- return (mUiAutomationService != null);
+ return (mUiAutomationService != null || !useAccessibility());
}
boolean suppressingAccessibilityServicesLocked() {
- return (mUiAutomationService != null) && ((mUiAutomationFlags
+ return (mUiAutomationService != null || !useAccessibility())
+ && ((mUiAutomationFlags
& UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0);
}
+ boolean useAccessibility() {
+ return ((mUiAutomationFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0);
+ }
+
boolean isTouchExplorationEnabledLocked() {
return (mUiAutomationService != null)
&& mUiAutomationService.mRequestTouchExplorationMode;
@@ -209,14 +222,14 @@
mUiAutomationService.onRemoved();
mUiAutomationService.resetLocked();
mUiAutomationService = null;
- mUiAutomationFlags = 0;
if (mUiAutomationServiceOwner != null) {
mUiAutomationServiceOwner.unlinkToDeath(
mUiAutomationServiceOwnerDeathRecipient, 0);
mUiAutomationServiceOwner = null;
}
- mSystemSupport.onClientChangeLocked(false);
}
+ mUiAutomationFlags = 0;
+ mSystemSupport.onClientChangeLocked(false);
}
}
@@ -227,9 +240,9 @@
int id, Handler mainHandler, Object lock,
AccessibilitySecurityPolicy securityPolicy,
SystemSupport systemSupport, WindowManagerInternal windowManagerInternal,
- SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) {
+ SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm) {
super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock,
- securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer,
+ securityPolicy, systemSupport, windowManagerInternal, systemActionPerformer,
awm);
mMainHandler = mainHandler;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index d8c5f6f..4bd987a 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -112,7 +112,7 @@
}
public String getSettingValue(ContentResolver resolver) {
- return Settings.Secure.getString(resolver, SETTING);
+ return Settings.Secure.getStringForUser(resolver, SETTING, resolver.getUserId());
}
public synchronized void update(KeyValueListParser parser) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 65ac784..d92706d 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -39,6 +39,7 @@
import android.os.BatteryProperty;
import android.os.BatteryStats;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.FileUtils;
@@ -59,6 +60,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.battery.BatteryServiceDumpProto;
+import android.sysprop.PowerProperties;
import android.util.EventLog;
import android.util.MutableInt;
import android.util.Slog;
@@ -182,6 +184,7 @@
private int mChargeStartLevel;
private boolean mUpdatesStopped;
+ private boolean mBatteryInputSuspended;
private Led mLed;
@@ -234,6 +237,8 @@
invalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
+
+ mBatteryInputSuspended = PowerProperties.battery_input_suspended().orElse(false);
}
@Override
@@ -876,6 +881,10 @@
pw.println(" reset [-f]");
pw.println(" Unfreeze battery state, returning to current hardware values.");
pw.println(" -f: force a battery change broadcast be sent, prints new sequence.");
+ if (Build.IS_DEBUGGABLE) {
+ pw.println(" disable_charge");
+ pw.println(" Suspend charging even if plugged in. ");
+ }
}
static final int OPTION_FORCE_UPDATE = 1<<0;
@@ -997,6 +1006,20 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
+ if (mBatteryInputSuspended) {
+ PowerProperties.battery_input_suspended(false);
+ mBatteryInputSuspended = false;
+ }
+ } break;
+ case "suspend_input": {
+ if (!Build.IS_DEBUGGABLE) {
+ throw new SecurityException(
+ "battery suspend_input is only supported on debuggable builds");
+ }
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+ PowerProperties.battery_input_suspended(true);
+ mBatteryInputSuspended = true;
} break;
default:
return shell.handleDefaultCommands(cmd);
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 3bcb36f..4de4075 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -19,6 +19,7 @@
import android.Manifest.permission;
import android.annotation.Nullable;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
@@ -404,7 +405,8 @@
}
public int getSecureInt(Context context, String name, int defaultValue) {
- return Settings.Secure.getInt(context.getContentResolver(), name, defaultValue);
+ final ContentResolver cr = context.getContentResolver();
+ return Settings.Secure.getIntForUser(cr, name, defaultValue, cr.getUserId());
}
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 27c5d4a..eb18da2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4687,14 +4687,19 @@
}
}
- public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) {
+ public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode,
+ int previousMode) {
final long token = Binder.clearCallingIdentity();
try {
// When using FUSE, we may need to kill the app if the op changes
switch(code) {
case OP_REQUEST_INSTALL_PACKAGES:
- // Always kill regardless of op change, to remount apps /storage
- killAppForOpChange(code, uid);
+ if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) {
+ // If we transition to/from MODE_ALLOWED, kill the app to make
+ // sure it has the correct view of /storage. Changing between
+ // MODE_DEFAULT / MODE_ERRORED is a no-op
+ killAppForOpChange(code, uid);
+ }
return;
case OP_MANAGE_EXTERNAL_STORAGE:
if (mode != MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 343e05d..20f3231 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -37,6 +37,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -116,6 +117,8 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -135,9 +138,31 @@
private static final boolean SHOW_DUNGEON_NOTIFICATION = false;
- //TODO: remove this when development is done.
- private static final int DEBUG_FGS_ALLOW_WHILE_IN_USE = 0;
- private static final int DEBUG_FGS_ENFORCE_TYPE = 1;
+ public static final int FGS_FEATURE_DENIED = 0;
+ public static final int FGS_FEATURE_ALLOWED_BY_PROC_STATE = 1;
+ public static final int FGS_FEATURE_ALLOWED_BY_UID_VISIBLE = 2;
+ public static final int FGS_FEATURE_ALLOWED_BY_FLAG = 3;
+ public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_UID = 4;
+ public static final int FGS_FEATURE_ALLOWED_BY_INSTR_PERMISSION = 5;
+ public static final int FGS_FEATURE_ALLOWED_BY_TOKEN = 6;
+ public static final int FGS_FEATURE_ALLOWED_BY_PERMISSION = 7;
+ public static final int FGS_FEATURE_ALLOWED_BY_WHITELIST = 8;
+ public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER = 9;
+
+ @IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = {
+ FGS_FEATURE_DENIED,
+ FGS_FEATURE_ALLOWED_BY_PROC_STATE,
+ FGS_FEATURE_ALLOWED_BY_UID_VISIBLE,
+ FGS_FEATURE_ALLOWED_BY_FLAG,
+ FGS_FEATURE_ALLOWED_BY_SYSTEM_UID,
+ FGS_FEATURE_ALLOWED_BY_INSTR_PERMISSION,
+ FGS_FEATURE_ALLOWED_BY_TOKEN,
+ FGS_FEATURE_ALLOWED_BY_PERMISSION,
+ FGS_FEATURE_ALLOWED_BY_WHITELIST,
+ FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FgsFeatureRetCode {}
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
@@ -519,12 +544,13 @@
}
if (fgRequired) {
- if (!r.mAllowStartForeground) {
+ if (isFgsBgStart(r.mAllowStartForeground)) {
if (!r.mLoggedInfoAllowStartForeground) {
Slog.wtf(TAG, "Background started FGS " + r.mInfoAllowStartForeground);
r.mLoggedInfoAllowStartForeground = true;
}
- if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
+ if (r.mAllowStartForeground == FGS_FEATURE_DENIED
+ && mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
Slog.w(TAG, "startForegroundService() not allowed due to "
+ " mAllowStartForeground false: service "
+ r.shortInstanceName);
@@ -768,9 +794,7 @@
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid,
r.name.getPackageName(), r.name.getClassName(),
FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
- synchronized (r.stats.getBatteryStats()) {
- r.stats.startRunningLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStartRunning(r.stats);
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
@@ -809,9 +833,7 @@
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid,
service.name.getPackageName(), service.name.getClassName(),
FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
- synchronized (service.stats.getBatteryStats()) {
- service.stats.stopRunningLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStopRunning(service.stats);
service.startRequested = false;
if (service.tracker != null) {
service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
@@ -970,9 +992,7 @@
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid,
r.name.getPackageName(), r.name.getClassName(),
FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
- synchronized (r.stats.getBatteryStats()) {
- r.stats.stopRunningLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStopRunning(r.stats);
r.startRequested = false;
if (r.tracker != null) {
r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
@@ -1427,13 +1447,14 @@
}
if (!ignoreForeground) {
- if (!r.mAllowStartForeground) {
+ if (isFgsBgStart(r.mAllowStartForeground)) {
if (!r.mLoggedInfoAllowStartForeground) {
Slog.wtf(TAG, "Background started FGS "
+ r.mInfoAllowStartForeground);
r.mLoggedInfoAllowStartForeground = true;
}
- if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
+ if (r.mAllowStartForeground == FGS_FEATURE_DENIED
+ && mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
Slog.w(TAG,
"Service.startForeground() not allowed due to "
+ "mAllowStartForeground false: service "
@@ -2518,7 +2539,8 @@
synchronized (stats) {
ss = stats.getServiceStatsLocked(
sInfo.applicationInfo.uid, name.getPackageName(),
- name.getClassName());
+ name.getClassName(), SystemClock.elapsedRealtime(),
+ SystemClock.uptimeMillis());
}
r = new ServiceRecord(mAm, ss, className, name, definingPackageName,
definingUid, filter, sInfo, callingFromFg, res);
@@ -3056,9 +3078,7 @@
}
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid,
r.name.getPackageName(), r.name.getClassName());
- synchronized (r.stats.getBatteryStats()) {
- r.stats.startLaunchedLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStartLaunch(r.stats);
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
@@ -3402,9 +3422,7 @@
smap.mDelayedStartList.remove(r);
if (r.app != null) {
- synchronized (r.stats.getBatteryStats()) {
- r.stats.stopLaunchedLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStopLaunch(r.stats);
r.app.stopService(r);
r.app.updateBoundClientUids();
if (r.whitelistManager) {
@@ -3940,9 +3958,7 @@
// Clear app state from services.
for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
ServiceRecord sr = app.getRunningServiceAt(i);
- synchronized (sr.stats.getBatteryStats()) {
- sr.stats.stopLaunchedLocked();
- }
+ mAm.mBatteryStatsService.noteServiceStopLaunch(sr.stats);
if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
sr.app.stopService(sr);
sr.app.updateBoundClientUids();
@@ -4885,13 +4901,13 @@
r.mAllowWhileInUsePermissionInFgs = true;
}
- if (!r.mAllowWhileInUsePermissionInFgs || !r.mAllowStartForeground) {
- final boolean temp = shouldAllowFgsFeatureLocked(callingPackage, callingPid,
- callingUid, intent, r, allowBackgroundActivityStarts);
+ if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == FGS_FEATURE_DENIED)) {
+ final @FgsFeatureRetCode int temp = shouldAllowFgsFeatureLocked(callingPackage,
+ callingPid, callingUid, intent, r, allowBackgroundActivityStarts);
if (!r.mAllowWhileInUsePermissionInFgs) {
- r.mAllowWhileInUsePermissionInFgs = temp;
+ r.mAllowWhileInUsePermissionInFgs = (temp != FGS_FEATURE_DENIED);
}
- if (!r.mAllowStartForeground) {
+ if (r.mAllowStartForeground == FGS_FEATURE_DENIED) {
r.mAllowStartForeground = temp;
}
}
@@ -4903,85 +4919,141 @@
* @param callingUid caller app's uid.
* @param intent intent to start/bind service.
* @param r the service to start.
- * @return true if allow, false otherwise.
+ * @return {@link FgsFeatureRetCode}
*/
- private boolean shouldAllowFgsFeatureLocked(String callingPackage,
+ private @FgsFeatureRetCode int shouldAllowFgsFeatureLocked(String callingPackage,
int callingPid, int callingUid, Intent intent, ServiceRecord r,
boolean allowBackgroundActivityStarts) {
- // Is the allow activity background start flag on?
- if (allowBackgroundActivityStarts) {
- return true;
- }
+ int ret = FGS_FEATURE_DENIED;
- boolean isCallerSystem = false;
- final int callingAppId = UserHandle.getAppId(callingUid);
- switch (callingAppId) {
- case ROOT_UID:
- case SYSTEM_UID:
- case NFC_UID:
- case SHELL_UID:
- isCallerSystem = true;
- break;
- default:
- isCallerSystem = false;
- break;
- }
-
- if (isCallerSystem) {
- return true;
- }
-
- if (r.app != null) {
- ActiveInstrumentation instr = r.app.getActiveInstrumentation();
- if (instr != null && instr.mHasBackgroundActivityStartsPermission) {
- return true;
- }
- if (r.app.areBackgroundActivityStartsAllowedByToken()) {
- return true;
- }
- }
-
- if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
- == PERMISSION_GRANTED) {
- return true;
- }
-
- // Is the calling UID at PROCESS_STATE_TOP or above?
+ final StringBuilder sb = new StringBuilder(64);
final int uidState = mAm.getUidState(callingUid);
- if (uidState <= ActivityManager.PROCESS_STATE_TOP) {
- return true;
+ if (ret == FGS_FEATURE_DENIED) {
+ // Is the calling UID at PROCESS_STATE_TOP or above?
+ if (uidState <= ActivityManager.PROCESS_STATE_TOP) {
+ sb.append("uidState=").append(uidState);
+ ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+ }
}
- // Does the calling UID have any visible activity?
- final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid);
- if (isCallingUidVisible) {
- return true;
+ if (ret == FGS_FEATURE_DENIED) {
+ // Does the calling UID have any visible activity?
+ final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid);
+ if (isCallingUidVisible) {
+ ret = FGS_FEATURE_ALLOWED_BY_UID_VISIBLE;
+ }
}
- final boolean isWhiteListedPackage =
- mWhiteListAllowWhileInUsePermissionInFgs.contains(callingPackage);
- if (isWhiteListedPackage) {
- return true;
+ if (ret == FGS_FEATURE_DENIED) {
+ // Is the allow activity background start flag on?
+ if (allowBackgroundActivityStarts) {
+ ret = FGS_FEATURE_ALLOWED_BY_FLAG;
+ }
}
- // Is the calling UID a device owner app?
- final boolean isDeviceOwner = mAm.mInternal.isDeviceOwner(callingUid);
- if (isDeviceOwner) {
- return true;
+ if (ret == FGS_FEATURE_DENIED) {
+ boolean isCallerSystem = false;
+ final int callingAppId = UserHandle.getAppId(callingUid);
+ switch (callingAppId) {
+ case ROOT_UID:
+ case SYSTEM_UID:
+ case NFC_UID:
+ case SHELL_UID:
+ isCallerSystem = true;
+ break;
+ default:
+ isCallerSystem = false;
+ break;
+ }
+
+ if (isCallerSystem) {
+ sb.append("callingUid=").append(callingAppId);
+ ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
+ }
}
- final String info =
+ if (ret == FGS_FEATURE_DENIED) {
+ if (r.app != null) {
+ ActiveInstrumentation instr = r.app.getActiveInstrumentation();
+ if (instr != null && instr.mHasBackgroundActivityStartsPermission) {
+ ret = FGS_FEATURE_ALLOWED_BY_INSTR_PERMISSION;
+ }
+ if (r.app.areBackgroundActivityStartsAllowedByToken()) {
+ ret = FGS_FEATURE_ALLOWED_BY_TOKEN;
+ }
+ }
+ }
+
+ if (ret == FGS_FEATURE_DENIED) {
+ if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
+ == PERMISSION_GRANTED) {
+ ret = FGS_FEATURE_ALLOWED_BY_PERMISSION;
+ }
+ }
+
+ if (ret == FGS_FEATURE_DENIED) {
+ final boolean isWhiteListedPackage =
+ mWhiteListAllowWhileInUsePermissionInFgs.contains(callingPackage);
+ if (isWhiteListedPackage) {
+ ret = FGS_FEATURE_ALLOWED_BY_WHITELIST;
+ }
+ }
+
+ if (ret == FGS_FEATURE_DENIED) {
+ // Is the calling UID a device owner app?
+ final boolean isDeviceOwner = mAm.mInternal.isDeviceOwner(callingUid);
+ if (isDeviceOwner) {
+ ret = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
+ }
+ }
+
+ final String debugInfo =
"[callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
+ "; uidState: " + ProcessList.makeProcStateString(uidState)
+ "; intent: " + intent
+ + "; code:" + fgsCodeToString(ret)
+ + "; extra:" + sb.toString()
+ "; targetSdkVersion:" + r.appInfo.targetSdkVersion
+ "]";
- if (!info.equals(r.mInfoAllowStartForeground)) {
+ if (!debugInfo.equals(r.mInfoAllowStartForeground)) {
r.mLoggedInfoAllowStartForeground = false;
- r.mInfoAllowStartForeground = info;
+ r.mInfoAllowStartForeground = debugInfo;
}
- return false;
+ return ret;
}
+
+ private static String fgsCodeToString(@FgsFeatureRetCode int code) {
+ switch (code) {
+ case FGS_FEATURE_DENIED:
+ return "DENIED";
+ case FGS_FEATURE_ALLOWED_BY_PROC_STATE:
+ return "ALLOWED_BY_PROC_STATE";
+ case FGS_FEATURE_ALLOWED_BY_UID_VISIBLE:
+ return "ALLOWED_BY_UID_VISIBLE";
+ case FGS_FEATURE_ALLOWED_BY_FLAG:
+ return "ALLOWED_BY_FLAG";
+ case FGS_FEATURE_ALLOWED_BY_SYSTEM_UID:
+ return "ALLOWED_BY_SYSTEM_UID";
+ case FGS_FEATURE_ALLOWED_BY_INSTR_PERMISSION:
+ return "ALLOWED_BY_INSTR_PERMISSION";
+ case FGS_FEATURE_ALLOWED_BY_TOKEN:
+ return "ALLOWED_BY_TOKEN";
+ case FGS_FEATURE_ALLOWED_BY_PERMISSION:
+ return "ALLOWED_BY_PERMISSION";
+ case FGS_FEATURE_ALLOWED_BY_WHITELIST:
+ return "ALLOWED_BY_WHITELIST";
+ case FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER:
+ return "ALLOWED_BY_DEVICE_OWNER";
+ default:
+ return "";
+ }
+ }
+
+ private static boolean isFgsBgStart(@FgsFeatureRetCode int code) {
+ return code != FGS_FEATURE_ALLOWED_BY_PROC_STATE
+ && code != FGS_FEATURE_ALLOWED_BY_UID_VISIBLE;
+ }
+
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a5d2011..b55d555 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -97,7 +97,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
@@ -110,7 +109,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_POWER;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROCESS_OBSERVERS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
@@ -133,18 +131,16 @@
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString;
-
import android.Manifest;
import android.Manifest.permission;
-import android.annotation.BroadcastBehavior;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -266,7 +262,6 @@
import android.os.storage.StorageManager;
import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
import android.provider.DeviceConfig;
-import android.provider.DeviceConfig.Properties;
import android.provider.Settings;
import android.server.ServerProtoEnums;
import android.sysprop.InitProperties;
@@ -342,7 +337,6 @@
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.UserspaceRebootLogger;
@@ -394,11 +388,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
public class ActivityManagerService extends IActivityManager.Stub
@@ -424,7 +414,6 @@
private static final String TAG_POWER = TAG + POSTFIX_POWER;
static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
static final String TAG_PROCESSES = TAG + POSTFIX_PROCESSES;
- 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;
static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
@@ -438,21 +427,9 @@
"com.android.internal.intent.action.BUGREPORT_REQUESTED";
private static final String SHELL_APP_PACKAGE = "com.android.shell";
- /** Control over CPU and battery monitoring */
- // write battery stats every 30 minutes.
- static final long BATTERY_STATS_TIME = 30 * 60 * 1000;
- static final boolean MONITOR_CPU_USAGE = true;
- // don't sample cpu less than every 5 seconds.
- static final long MONITOR_CPU_MIN_TIME = 5 * 1000;
- // wait possibly forever for next cpu sample.
- static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;
- static final boolean MONITOR_THREAD_CPU_USAGE = false;
-
// The flags that are set for all calls we make to the package manager.
public static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
- static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
-
static final String SYSTEM_USER_HOME_NEEDED = "ro.system_user_home_needed";
public static final String ANR_TRACE_DIR = "/data/anr";
@@ -495,37 +472,6 @@
private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
"com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
- /**
- * Broadcast sent when heap dump collection has been completed.
- */
- @BroadcastBehavior(includeBackground = true, protectedBroadcast = true)
- private static final String ACTION_HEAP_DUMP_FINISHED =
- "com.android.internal.intent.action.HEAP_DUMP_FINISHED";
-
- /**
- * The process we are reporting
- */
- private static final String EXTRA_HEAP_DUMP_PROCESS_NAME =
- "com.android.internal.extra.heap_dump.PROCESS_NAME";
-
- /**
- * The size limit the process reached.
- */
- private static final String EXTRA_HEAP_DUMP_SIZE_BYTES =
- "com.android.internal.extra.heap_dump.SIZE_BYTES";
-
- /**
- * Whether the user initiated the dump or not.
- */
- private static final String EXTRA_HEAP_DUMP_IS_USER_INITIATED =
- "com.android.internal.extra.heap_dump.IS_USER_INITIATED";
-
- /**
- * Optional name of package to directly launch.
- */
- private static final String EXTRA_HEAP_DUMP_REPORT_PACKAGE =
- "com.android.internal.extra.heap_dump.REPORT_PACKAGE";
-
// If set, we will push process association information in to procstats.
static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true;
@@ -558,7 +504,6 @@
private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
OomAdjuster mOomAdjuster;
- final LowMemDetector mLowMemDetector;
static final String EXTRA_TITLE = "android.intent.extra.TITLE";
static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
@@ -920,28 +865,11 @@
*/
final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<ProcessRecord>();
- /**
- * Processes we want to collect PSS data from.
- */
- final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
-
- /**
- * Depth of overlapping activity-start PSS deferral notes
- */
- private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0);
-
private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
new ActivityMetricsLaunchObserver() {
@Override
public void onActivityLaunched(byte[] activity, int temperature) {
- // This is safe to force to the head of the queue because it relies only
- // on refcounting to track begin/end of deferrals, not on actual
- // message ordering. We don't care *what* activity is being
- // launched; only that we're doing so.
- if (mPssDeferralTime > 0) {
- final Message msg = mBgHandler.obtainMessage(DEFER_PSS_MSG);
- mBgHandler.sendMessageAtFrontOfQueue(msg);
- }
+ mAppProfiler.onActivityLaunched();
}
// The other observer methods are unused
@@ -966,45 +894,9 @@
}
};
- /**
- * How long we defer PSS gathering while activities are starting, in milliseconds.
- * This is adjustable via DeviceConfig. If it is zero or negative, no PSS deferral
- * is done.
- */
- private volatile long mPssDeferralTime = 0;
- private static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer";
-
private boolean mBinderTransactionTrackingEnabled = false;
/**
- * Last time we requested PSS data of all processes.
- */
- long mLastFullPssTime = SystemClock.uptimeMillis();
-
- /**
- * If set, the next time we collect PSS data we should do a full collection
- * with data from native processes and the kernel.
- */
- boolean mFullPssPending = false;
-
- /**
- * Observe DeviceConfig changes to the PSS calculation interval
- */
- private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener =
- new DeviceConfig.OnPropertiesChangedListener() {
- @Override
- public void onPropertiesChanged(Properties properties) {
- if (properties.getKeyset().contains(ACTIVITY_START_PSS_DEFER_CONFIG)) {
- mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "Activity-start PSS delay now "
- + mPssDeferralTime + " ms");
- }
- }
- }
- };
-
- /**
* Fingerprints (hashCode()) of stack traces that we've
* already logged DropBox entries for. Guarded by itself. If
* something (rogue user app) forces this over
@@ -1244,41 +1136,11 @@
int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
/**
- * Allow the current computed overall memory level of the system to go down?
- * This is set to false when we are killing processes for reasons other than
- * memory management, so that the now smaller process list will not be taken as
- * an indication that memory is tighter.
- */
- boolean mAllowLowerMemLevel = false;
-
- /**
- * The last computed memory level, for holding when we are in a state that
- * processes are going away for other reasons.
- */
- int mLastMemoryLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
-
- /**
- * The last total number of process we have, to determine if changes actually look
- * like a shrinking number of process due to lower RAM.
- */
- int mLastNumProcesses;
-
- /**
* The uptime of the last time we performed idle maintenance.
*/
long mLastIdleTime = SystemClock.uptimeMillis();
/**
- * Total time spent with RAM that has been added in the past since the last idle time.
- */
- long mLowRamTimeSinceLastIdle = 0;
-
- /**
- * If RAM is currently low, when that horrible situation started.
- */
- long mLowRamStartTime = 0;
-
- /**
* For reporting to battery stats the current top application.
*/
private String mCurResumedPackage = null;
@@ -1297,13 +1159,6 @@
*/
boolean mSafeMode;
- /**
- * If true, we are running under a test environment so will sample PSS from processes
- * much more rapidly to try to collect better data when the tests are rapidly
- * running through apps.
- */
- boolean mTestPssMode = false;
-
String mDebugApp = null;
boolean mWaitForDebugger = false;
boolean mDebugTransient = false;
@@ -1311,61 +1166,6 @@
boolean mOrigWaitForDebugger = false;
boolean mAlwaysFinishActivities = false;
- class ProfileData {
- private String mProfileApp = null;
- private ProcessRecord mProfileProc = null;
- private ProfilerInfo mProfilerInfo = null;
-
- void setProfileApp(String profileApp) {
- mProfileApp = profileApp;
- if (mAtmInternal != null) {
- mAtmInternal.setProfileApp(profileApp);
- }
- }
-
- String getProfileApp() {
- return mProfileApp;
- }
-
- void setProfileProc(ProcessRecord profileProc) {
- mProfileProc = profileProc;
- if (mAtmInternal != null) {
- mAtmInternal.setProfileProc(profileProc == null ? null
- : profileProc.getWindowProcessController());
- }
- }
-
- ProcessRecord getProfileProc() {
- return mProfileProc;
- }
-
- void setProfilerInfo(ProfilerInfo profilerInfo) {
- mProfilerInfo = profilerInfo;
- if (mAtmInternal != null) {
- mAtmInternal.setProfilerInfo(profilerInfo);
- }
- }
-
- ProfilerInfo getProfilerInfo() {
- return mProfilerInfo;
- }
- }
- final ProfileData mProfileData = new ProfileData();
-
- /**
- * Stores a map of process name -> agent string. When a process is started and mAgentAppMap
- * is not null, this map is checked and the mapped agent installed during bind-time. Note:
- * A non-null agent in mProfileInfo overrides this.
- */
- private @Nullable Map<String, String> mAppAgentMap = null;
-
- int mProfileType = 0;
- final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
- String mMemWatchDumpProcName;
- Uri mMemWatchDumpUri;
- int mMemWatchDumpPid;
- int mMemWatchDumpUid;
- private boolean mMemWatchIsUserInitiated;
String mTrackAllocationApp = null;
String mNativeDebuggingApp = null;
@@ -1404,27 +1204,6 @@
final AnrHelper mAnrHelper = new AnrHelper(this);
- /**
- * Runtime CPU use collection thread. This object's lock is used to
- * perform synchronization with the thread (notifying it to run).
- */
- final Thread mProcessCpuThread;
-
- /**
- * Used to collect per-process CPU use for ANRs, battery stats, etc.
- * Must acquire this object's lock when accessing it.
- * NOTE: this lock will be held while doing long operations (trawling
- * through all processes in /proc), so it should never be acquired by
- * any critical paths such as when holding the main activity manager lock.
- */
- final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(
- MONITOR_THREAD_CPU_USAGE);
- final AtomicLong mLastCpuTime = new AtomicLong(0);
- final AtomicBoolean mProcessCpuMutexFree = new AtomicBoolean(true);
- final CountDownLatch mProcessCpuInitLatch = new CountDownLatch(1);
-
- long mLastWriteTime = 0;
-
/** Set to true after the system has finished booting. */
volatile boolean mBooted = false;
@@ -1563,6 +1342,23 @@
*/
private long mLastBinderHeavyHitterAutoSamplerStart = 0L;
+ final AppProfiler mAppProfiler;
+
+ private static final int INDEX_NATIVE_PSS = 0;
+ private static final int INDEX_NATIVE_SWAP_PSS = 1;
+ private static final int INDEX_NATIVE_RSS = 2;
+ private static final int INDEX_DALVIK_PSS = 3;
+ private static final int INDEX_DALVIK_SWAP_PSS = 4;
+ private static final int INDEX_DALVIK_RSS = 5;
+ private static final int INDEX_OTHER_PSS = 6;
+ private static final int INDEX_OTHER_SWAP_PSS = 7;
+ private static final int INDEX_OTHER_RSS = 8;
+ private static final int INDEX_TOTAL_PSS = 9;
+ private static final int INDEX_TOTAL_SWAP_PSS = 10;
+ private static final int INDEX_TOTAL_RSS = 11;
+ private static final int INDEX_TOTAL_NATIVE_PSS = 12;
+ private static final int INDEX_LAST = 13;
+
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -1754,63 +1550,10 @@
break;
}
case POST_DUMP_HEAP_NOTIFICATION_MSG: {
- final String procName;
- final int uid;
- final long memLimit;
- final String reportPackage;
- final boolean isUserInitiated;
- synchronized (ActivityManagerService.this) {
- uid = mMemWatchDumpUid;
- procName = mMemWatchDumpProcName;
- Pair<Long, String> val = mMemWatchProcesses.get(procName, uid);
- if (val == null) {
- val = mMemWatchProcesses.get(procName, 0);
- }
- if (val != null) {
- memLimit = val.first;
- reportPackage = val.second;
- } else {
- memLimit = 0;
- reportPackage = null;
- }
- isUserInitiated = mMemWatchIsUserInitiated;
-
- mMemWatchDumpUri = null;
- mMemWatchDumpProcName = null;
- mMemWatchDumpPid = -1;
- mMemWatchDumpUid = -1;
- }
- if (procName == null) {
- return;
- }
-
- if (DEBUG_PSS) Slog.d(TAG_PSS,
- "Showing dump heap notification from " + procName + "/" + uid);
-
- Intent dumpFinishedIntent = new Intent(ACTION_HEAP_DUMP_FINISHED);
- // Send this only to the Shell package.
- dumpFinishedIntent.setPackage("com.android.shell");
- dumpFinishedIntent.putExtra(Intent.EXTRA_UID, uid);
- dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_IS_USER_INITIATED, isUserInitiated);
- dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_SIZE_BYTES, memLimit);
- dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_REPORT_PACKAGE, reportPackage);
- dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_PROCESS_NAME, procName);
-
- mContext.sendBroadcastAsUser(dumpFinishedIntent,
- UserHandle.getUserHandleForUid(uid));
+ mAppProfiler.handlePostDumpHeapNotification();
} break;
case ABORT_DUMPHEAP_MSG: {
- String procName = (String) msg.obj;
- if (procName != null) {
- synchronized (ActivityManagerService.this) {
- if (procName.equals(mMemWatchDumpProcName)) {
- mMemWatchDumpProcName = null;
- mMemWatchDumpUri = null;
- mMemWatchDumpPid = -1;
- mMemWatchDumpUid = -1;
- }
- }
- }
+ mAppProfiler.handleAbortDumpHeap((String) msg.obj);
} break;
case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: {
IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj;
@@ -1843,147 +1586,6 @@
}
}
- static final int COLLECT_PSS_BG_MSG = 1;
- static final int DEFER_PSS_MSG = 2;
- static final int STOP_DEFERRING_PSS_MSG = 3;
-
- final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case COLLECT_PSS_BG_MSG: {
- long start = SystemClock.uptimeMillis();
- MemInfoReader memInfo = null;
- synchronized (ActivityManagerService.this) {
- if (mFullPssPending) {
- mFullPssPending = false;
- memInfo = new MemInfoReader();
- }
- }
- if (memInfo != null) {
- updateCpuStatsNow();
- long nativeTotalPss = 0;
- final List<ProcessCpuTracker.Stats> stats;
- synchronized (mProcessCpuTracker) {
- stats = mProcessCpuTracker.getStats( (st)-> {
- return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
- });
- }
- final int N = stats.size();
- for (int j = 0; j < N; j++) {
- synchronized (mPidsSelfLocked) {
- if (mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) {
- // This is one of our own processes; skip it.
- continue;
- }
- }
- nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null);
- }
- memInfo.readMemInfo();
- synchronized (mProcessStats.mLock) {
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Collected native and kernel memory in "
- + (SystemClock.uptimeMillis()-start) + "ms");
- final long cachedKb = memInfo.getCachedSizeKb();
- final long freeKb = memInfo.getFreeSizeKb();
- final long zramKb = memInfo.getZramTotalSizeKb();
- final long kernelKb = memInfo.getKernelUsedSizeKb();
- EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
- kernelKb*1024, nativeTotalPss*1024);
- mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
- nativeTotalPss);
- }
- }
-
- int num = 0;
- long[] tmp = new long[3];
- do {
- ProcessRecord proc;
- int procState;
- int statType;
- int pid = -1;
- long lastPssTime;
- synchronized (ActivityManagerService.this) {
- if (mPendingPssProcesses.size() <= 0) {
- if (mTestPssMode || DEBUG_PSS) Slog.d(TAG_PSS,
- "Collected pss of " + num + " processes in "
- + (SystemClock.uptimeMillis() - start) + "ms");
- mPendingPssProcesses.clear();
- return;
- }
- proc = mPendingPssProcesses.remove(0);
- procState = proc.pssProcState;
- statType = proc.pssStatType;
- lastPssTime = proc.lastPssTime;
- long now = SystemClock.uptimeMillis();
- if (proc.thread != null && procState == proc.setProcState
- && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
- < now) {
- pid = proc.pid;
- } else {
- ProcessList.abortNextPssTime(proc.procStateMemTracker);
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid +
- ": still need " +
- (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE-now) +
- "ms until safe");
- proc = null;
- pid = 0;
- }
- }
- if (proc != null) {
- long startTime = SystemClock.currentThreadTimeMillis();
- // skip background PSS calculation of apps that are capturing
- // camera imagery
- final boolean usingCamera = isCameraActiveForUid(proc.uid);
- long pss = usingCamera ? 0 : Debug.getPss(pid, tmp, null);
- long endTime = SystemClock.currentThreadTimeMillis();
- synchronized (ActivityManagerService.this) {
- if (pss != 0 && proc.thread != null && proc.setProcState == procState
- && proc.pid == pid && proc.lastPssTime == lastPssTime) {
- num++;
- ProcessList.commitNextPssTime(proc.procStateMemTracker);
- recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1], tmp[2],
- statType, endTime-startTime, SystemClock.uptimeMillis());
- } else {
- ProcessList.abortNextPssTime(proc.procStateMemTracker);
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid +
- ": " + (proc.thread == null ? "NO_THREAD " : "") +
- (usingCamera ? "CAMERA " : "") +
- (proc.pid != pid ? "PID_CHANGED " : "") +
- " initState=" + procState + " curState=" +
- proc.setProcState + " " +
- (proc.lastPssTime != lastPssTime ? "TIME_CHANGED" : ""));
- }
- }
- }
- } while (true);
- }
-
- case DEFER_PSS_MSG: {
- deferPssForActivityStart();
- } break;
-
- case STOP_DEFERRING_PSS_MSG: {
- final int nesting = mActivityStartingNesting.decrementAndGet();
- if (nesting <= 0) {
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now "
- + nesting);
- }
- if (nesting < 0) {
- Slog.wtf(TAG, "Activity start nesting undercount!");
- mActivityStartingNesting.incrementAndGet();
- }
- } else {
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting);
- }
- }
- }
- break;
-
- }
- }
- };
public void setSystemProcess() {
try {
@@ -1994,10 +1596,7 @@
DUMP_FLAG_PRIORITY_HIGH);
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
- if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(this),
- /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
- }
+ mAppProfiler.setCpuInfoService();
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
ServiceManager.addService("cacheinfo", new CacheBinder(this));
@@ -2154,37 +1753,6 @@
}
}
- static class CpuBinder extends Binder {
- ActivityManagerService mActivityManagerService;
- private final PriorityDump.PriorityDumper mPriorityDumper =
- new PriorityDump.PriorityDumper() {
- @Override
- public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
- boolean asProto) {
- if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
- "cpuinfo", pw)) return;
- synchronized (mActivityManagerService.mProcessCpuTracker) {
- if (asProto) {
- mActivityManagerService.mProcessCpuTracker.dumpProto(fd);
- return;
- }
- pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad());
- pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState(
- SystemClock.uptimeMillis()));
- }
- }
- };
-
- CpuBinder(ActivityManagerService activityManagerService) {
- mActivityManagerService = activityManagerService;
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- PriorityDump.dump(mPriorityDumper, fd, pw, args);
- }
- }
-
static class CacheBinder extends Binder {
ActivityManagerService mActivityManagerService;
@@ -2427,13 +1995,12 @@
mPlatformCompat = null;
mProcessList = injector.getProcessList(this);
mProcessList.init(this, activeUids, mPlatformCompat);
- mLowMemDetector = null;
+ mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(), null);
mOomAdjuster = hasHandlerThread
? new OomAdjuster(this, mProcessList, activeUids, handlerThread) : null;
mIntentFirewall = hasHandlerThread
? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
- mProcessCpuThread = null;
mProcessStats = null;
mCpHelper = new ContentProviderHelper(this, false);
// For the usage of {@link ActiveServices#cleanUpServices} that may be invoked from
@@ -2484,7 +2051,8 @@
Context.PLATFORM_COMPAT_SERVICE);
mProcessList = mInjector.getProcessList(this);
mProcessList.init(this, activeUids, mPlatformCompat);
- mLowMemDetector = new LowMemDetector(this);
+ mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(),
+ new LowMemDetector(this));
mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
// Broadcast policy parameters
@@ -2556,40 +2124,6 @@
DisplayThread.get().getLooper());
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
- mProcessCpuThread = new Thread("CpuTracker") {
- @Override
- public void run() {
- synchronized (mProcessCpuTracker) {
- mProcessCpuInitLatch.countDown();
- mProcessCpuTracker.init();
- }
- while (true) {
- try {
- try {
- synchronized(this) {
- final long now = SystemClock.uptimeMillis();
- long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
- long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
- //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
- // + ", write delay=" + nextWriteDelay);
- if (nextWriteDelay < nextCpuDelay) {
- nextCpuDelay = nextWriteDelay;
- }
- if (nextCpuDelay > 0) {
- mProcessCpuMutexFree.set(true);
- this.wait(nextCpuDelay);
- }
- }
- } catch (InterruptedException e) {
- }
- updateCpuStatsNow();
- } catch (Exception e) {
- Slog.e(TAG, "Unexpected exception collecting process stats", e);
- }
- }
- }
- };
-
mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
Watchdog.getInstance().addMonitor(this);
@@ -2623,7 +2157,6 @@
private void start() {
removeAllProcessGroups();
- mProcessCpuThread.start();
mBatteryStatsService.publish();
mAppOpsService.publish();
@@ -2631,16 +2164,7 @@
LocalServices.addService(ActivityManagerInternal.class, mInternal);
mActivityTaskManager.onActivityManagerInternalAdded();
mPendingIntentController.onActivityManagerInternalAdded();
- // Wait for the synchronized block started in mProcessCpuThread,
- // so that any other access to mProcessCpuTracker from main thread
- // will be blocked during mProcessCpuTracker initialization.
- try {
- mProcessCpuInitLatch.await();
- } catch (InterruptedException e) {
- Slog.wtf(TAG, "Interrupted wait during start", e);
- Thread.currentThread().interrupt();
- throw new IllegalStateException("Interrupted wait during start");
- }
+ mAppProfiler.onActivityManagerInternalAdded();
}
public void initPowerManagement() {
@@ -2783,111 +2307,12 @@
}
}
- void updateCpuStats() {
- final long now = SystemClock.uptimeMillis();
- if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
- return;
- }
- if (mProcessCpuMutexFree.compareAndSet(true, false)) {
- synchronized (mProcessCpuThread) {
- mProcessCpuThread.notify();
- }
- }
+ void updateCpuStatsLocked() {
+ mAppProfiler.updateCpuStatsLocked();
}
void updateCpuStatsNow() {
- synchronized (mProcessCpuTracker) {
- mProcessCpuMutexFree.set(false);
- final long now = SystemClock.uptimeMillis();
- boolean haveNewCpuStats = false;
-
- if (MONITOR_CPU_USAGE &&
- mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
- mLastCpuTime.set(now);
- mProcessCpuTracker.update();
- if (mProcessCpuTracker.hasGoodLastStats()) {
- haveNewCpuStats = true;
- //Slog.i(TAG, mProcessCpu.printCurrentState());
- //Slog.i(TAG, "Total CPU usage: "
- // + mProcessCpu.getTotalCpuPercent() + "%");
-
- // Slog the cpu usage if the property is set.
- if ("true".equals(SystemProperties.get("events.cpu"))) {
- int user = mProcessCpuTracker.getLastUserTime();
- int system = mProcessCpuTracker.getLastSystemTime();
- int iowait = mProcessCpuTracker.getLastIoWaitTime();
- int irq = mProcessCpuTracker.getLastIrqTime();
- int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
- int idle = mProcessCpuTracker.getLastIdleTime();
-
- int total = user + system + iowait + irq + softIrq + idle;
- if (total == 0) total = 1;
-
- EventLogTags.writeCpu(
- ((user + system + iowait + irq + softIrq) * 100) / total,
- (user * 100) / total,
- (system * 100) / total,
- (iowait * 100) / total,
- (irq * 100) / total,
- (softIrq * 100) / total);
- }
- }
- }
-
- final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
- synchronized(bstats) {
- synchronized(mPidsSelfLocked) {
- if (haveNewCpuStats) {
- if (bstats.startAddingCpuLocked()) {
- int totalUTime = 0;
- int totalSTime = 0;
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (!st.working) {
- continue;
- }
- ProcessRecord pr = mPidsSelfLocked.get(st.pid);
- totalUTime += st.rel_utime;
- totalSTime += st.rel_stime;
- if (pr != null) {
- BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
- if (ps == null || !ps.isActive()) {
- pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
- pr.info.uid, pr.processName);
- }
- ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
- pr.curCpuTime += st.rel_utime + st.rel_stime;
- if (pr.lastCpuTime == 0) {
- pr.lastCpuTime = pr.curCpuTime;
- }
- } else {
- BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
- if (ps == null || !ps.isActive()) {
- st.batteryStats = ps = bstats.getProcessStatsLocked(
- bstats.mapUid(st.uid), st.name);
- }
- ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
- }
- }
- final int userTime = mProcessCpuTracker.getLastUserTime();
- final int systemTime = mProcessCpuTracker.getLastSystemTime();
- final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
- final int irqTime = mProcessCpuTracker.getLastIrqTime();
- final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
- final int idleTime = mProcessCpuTracker.getLastIdleTime();
- bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime,
- systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
- }
- }
- }
-
- if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
- mLastWriteTime = now;
- mBatteryStatsService.scheduleWriteToDisk();
- }
- }
- }
+ mAppProfiler.updateCpuStatsNow();
}
@Override
@@ -3076,18 +2501,8 @@
Slog.d(TAG_SWITCH,
"updateBatteryStats: comp=" + activity + "res=" + resumed);
}
- final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
- uid, activity.getPackageName(), activity.getShortClassName(),
- resumed ? FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND :
- FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND);
- synchronized (stats) {
- if (resumed) {
- stats.noteActivityResumedLocked(uid);
- } else {
- stats.noteActivityPausedLocked(uid);
- }
- }
+ mBatteryStatsService.updateBatteryStatsOnActivityUsage(activity.getPackageName(),
+ activity.getShortClassName(), uid, userId, resumed);
}
/**
@@ -3517,9 +2932,7 @@
}
}
- if (mProfileData.getProfileProc() == app) {
- clearProfilerLocked();
- }
+ mAppProfiler.onAppDiedLocked(app);
mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {
Slog.w(TAG, "Crash of app " + app.processName
@@ -3563,7 +2976,7 @@
// and the app that died was not running instrumentation,
// then tell everyone we are now low on memory.
if (!mProcessList.haveBackgroundProcessLocked()) {
- boolean doReport = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+ boolean doReport = Build.IS_DEBUGGABLE;
if (doReport) {
long now = SystemClock.uptimeMillis();
if (now < (mLastMemUsageReportTime+5*60*1000)) {
@@ -3626,10 +3039,7 @@
}
}
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- stats.noteProcessDiedLocked(app.info.uid, pid);
- }
+ mBatteryStatsService.noteProcessDied(app.info.uid, pid);
if (!app.killed) {
if (!fromBinderDied) {
@@ -3651,11 +3061,11 @@
"Process " + app.processName + " (pid " + pid + ") has died: "
+ ProcessList.makeOomAdjString(app.setAdj, true) + " "
+ ProcessList.makeProcStateString(app.setProcState), app.info.uid);
- mAllowLowerMemLevel = true;
+ mAppProfiler.setAllowLowerMemLevelLocked(true);
} else {
// Note that we always want to do oom adj to update our state with the
// new number of procs.
- mAllowLowerMemLevel = false;
+ mAppProfiler.setAllowLowerMemLevelLocked(false);
doLowMem = false;
}
EventLogTags.writeAmProcDied(app.userId, app.pid, app.processName, app.setAdj,
@@ -4151,7 +3561,7 @@
synchronized (this) {
// Allow memory level to go down (the flag needs to be set before updating oom adj)
// because this method is also used to simulate low memory.
- mAllowLowerMemLevel = true;
+ mAppProfiler.setAllowLowerMemLevelLocked(true);
mProcessList.killPackageProcessesLocked(null /* packageName */, -1 /* appId */,
UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ,
ApplicationExitInfo.REASON_USER_REQUESTED,
@@ -4936,48 +4346,7 @@
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
app.compat = compatibilityInfoForPackage(appInfo);
- ProfilerInfo profilerInfo = null;
- String preBindAgent = null;
- if (mProfileData.getProfileApp() != null
- && mProfileData.getProfileApp().equals(processName)) {
- mProfileData.setProfileProc(app);
- if (mProfileData.getProfilerInfo() != null) {
- // Send a profiler info object to the app if either a file is given, or
- // an agent should be loaded at bind-time.
- boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
- || mProfileData.getProfilerInfo().attachAgentDuringBind;
- profilerInfo = needsInfo
- ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
- if (mProfileData.getProfilerInfo().agent != null) {
- preBindAgent = mProfileData.getProfilerInfo().agent;
- }
- }
- } else if (instr != null && instr.mProfileFile != null) {
- profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
- null, false);
- }
- if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
- // We need to do a debuggable check here. See setAgentApp for why the check is
- // postponed to here.
- if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- String agent = mAppAgentMap.get(processName);
- // Do not overwrite already requested agent.
- if (profilerInfo == null) {
- profilerInfo = new ProfilerInfo(null, null, 0, false, false,
- mAppAgentMap.get(processName), true);
- } else if (profilerInfo.agent == null) {
- profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
- }
- }
- }
-
- if (profilerInfo != null && profilerInfo.profileFd != null) {
- profilerInfo.profileFd = profilerInfo.profileFd.dup();
- if (TextUtils.equals(mProfileData.getProfileApp(), processName)
- && mProfileData.getProfilerInfo() != null) {
- clearProfilerLocked();
- }
- }
+ ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);
// We deprecated Build.SERIAL and it is not accessible to
// Instant Apps and target APIs higher than O MR1. Since access to the serial
@@ -4986,44 +4355,6 @@
&& appInfo.targetSdkVersion < Build.VERSION_CODES.P)
? sTheRealBuildSerial : Build.UNKNOWN;
- // Check if this is a secondary process that should be incorporated into some
- // currently active instrumentation. (Note we do this AFTER all of the profiling
- // stuff above because profiling can currently happen only in the primary
- // instrumentation process.)
- if (mActiveInstrumentation.size() > 0 && instr == null) {
- for (int i = mActiveInstrumentation.size() - 1;
- i >= 0 && app.getActiveInstrumentation() == null; i--) {
- ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
- if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
- if (aInstr.mTargetProcesses.length == 0) {
- // This is the wildcard mode, where every process brought up for
- // the target instrumentation should be included.
- if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
- app.setActiveInstrumentation(aInstr);
- aInstr.mRunningProcesses.add(app);
- }
- } else {
- for (String proc : aInstr.mTargetProcesses) {
- if (proc.equals(app.processName)) {
- app.setActiveInstrumentation(aInstr);
- aInstr.mRunningProcesses.add(app);
- break;
- }
- }
- }
- }
- }
- }
-
- // If we were asked to attach an agent on startup, do so now, before we're binding
- // application code.
- if (preBindAgent != null) {
- thread.attachAgent(preBindAgent);
- }
- if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- thread.attachStartupAgents(app.info.dataDir);
- }
-
// Figure out whether the app needs to run in autofill compat mode.
AutofillOptions autofillOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
@@ -5312,7 +4643,8 @@
boolean sticky, int sendingUser) {
synchronized (ActivityManagerService.this) {
mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
- requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
+ mAppProfiler.requestPssAllProcsLocked(
+ SystemClock.uptimeMillis(), true, false);
}
}
});
@@ -6418,8 +5750,8 @@
}
@Override
- public List<StackInfo> getAllStackInfos() {
- return mActivityTaskManager.getAllStackInfos();
+ public List<RootTaskInfo> getAllRootTaskInfos() {
+ return mActivityTaskManager.getAllRootTaskInfos();
}
@Override
@@ -6912,32 +6244,13 @@
"Requires permission " + android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
- if (agent == null) {
- if (mAppAgentMap != null) {
- mAppAgentMap.remove(packageName);
- if (mAppAgentMap.isEmpty()) {
- mAppAgentMap = null;
- }
- }
- } else {
- if (mAppAgentMap == null) {
- mAppAgentMap = new HashMap<>();
- }
- if (mAppAgentMap.size() >= 100) {
- // Limit the size of the map, to avoid OOMEs.
- Slog.e(TAG, "App agent map has too many entries, cannot add " + packageName
- + "/" + agent);
- return;
- }
- mAppAgentMap.put(packageName, agent);
- }
+ mAppProfiler.setAgentAppLocked(packageName, agent);
}
}
void setTrackAllocationApp(ApplicationInfo app, String processName) {
synchronized (this) {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
+ if (!Build.IS_DEBUGGABLE) {
if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
throw new SecurityException("Process not debuggable: " + app.packageName);
}
@@ -6949,8 +6262,7 @@
void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo) {
synchronized (this) {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
+ if (!Build.IS_DEBUGGABLE) {
boolean isAppDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
boolean isAppProfileable = app.isProfileableByShell();
if (!isAppDebuggable && !isAppProfileable) {
@@ -6958,24 +6270,12 @@
+ "and not profileable by shell: " + app.packageName);
}
}
- mProfileData.setProfileApp(processName);
-
- if (mProfileData.getProfilerInfo() != null) {
- if (mProfileData.getProfilerInfo().profileFd != null) {
- try {
- mProfileData.getProfilerInfo().profileFd.close();
- } catch (IOException e) {
- }
- }
- }
- mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
- mProfileType = 0;
+ mAppProfiler.setProfileAppLocked(processName, profilerInfo);
}
}
void setNativeDebuggingAppLocked(ApplicationInfo app, String processName) {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
+ if (!Build.IS_DEBUGGABLE) {
if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
throw new SecurityException("Process not debuggable: " + app.packageName);
}
@@ -7057,7 +6357,7 @@
return;
}
synchronized (this) {
- startHeapDumpLocked(pr, true);
+ mAppProfiler.startHeapDumpLocked(pr, true);
}
}
@@ -7300,53 +6600,6 @@
return uidRecord != null && !uidRecord.setIdle;
}
- /**
- * Change the sched policy cgroup of a thread.
- *
- * <p>It is intended to be used in jni call of {@link Process#setThreadPriority(int, int)}.
- * When a process is changing the priority of its threads, the sched policy of that
- * thread may need to be changed accordingly - if the priority is changed to below
- * or equal to {@link android.os.Process#THREAD_PRIORITY_BACKGROUND} or raising from it.
- * However, because of the limitation of sepolicy, the thread priority change will
- * fail for some processes. To solve it, we add this binder call in Activity Manager,
- * so that the jni call of {@link Process#setThreadPriority(int, int)} could use it.
- *
- * @param tid tid of the thread to be changed.
- * @param group The sched policy group to be changed to.
- *
- * @throws IllegalArgumentException if group is invalid.
- * @throws SecurityException if no permission.
- *
- * @return Returns {@code true} if the sched policy is changed successfully;
- * {@code false} otherwise.
- */
- @Override
- public boolean setSchedPolicyCgroup(final int tid, final int group) {
- final int pid = Binder.getCallingPid();
- final int tgid = Process.getThreadGroupLeader(tid);
- final int pgroup = Process.getProcessGroup(pid);
-
- // tid is not in the thread group of caller
- if (pid != tgid) {
- return false;
- }
-
- // sched group is higher than its main process
- if (group > pgroup) {
- return false;
- }
-
- try {
- Process.setThreadGroup(tid, group);
- return true;
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Failed to set thread group, argument invalid:\n" + e);
- } catch (SecurityException e) {
- Slog.w(TAG, "Failed to set thread group, no permission:\n" + e);
- }
- return false;
- }
-
@Override
public void setPersistentVrThread(int tid) {
mActivityTaskManager.setPersistentVrThread(tid);
@@ -7880,10 +7133,6 @@
br.onReceive(mContext, intent);
}
- private long getLowRamTimeSinceIdle(long now) {
- return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now-mLowRamStartTime) : 0);
- }
-
@Override
public void performIdleMaintenance() {
if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
@@ -7899,12 +7148,9 @@
// Compact all non-zygote processes to freshen up the page cache.
mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
- final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now);
+ final long lowRamSinceLastIdle = mAppProfiler.getLowRamTimeSinceIdleLocked(now);
mLastIdleTime = now;
- mLowRamTimeSinceLastIdle = 0;
- if (mLowRamStartTime != 0) {
- mLowRamStartTime = now;
- }
+ mAppProfiler.updateLowRamTimestampLocked(now);
StringBuilder sb = new StringBuilder(128);
sb.append("Idle maintenance over ");
@@ -7955,8 +7201,7 @@
&& proc.setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
proc.notCachedSinceIdle = true;
proc.initialIdlePss = 0;
- proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, null,
- mTestPssMode, mAtmInternal.isSleeping(), now);
+ mAppProfiler.updateNextPssTimeLocked(proc.setProcState, proc, now, true);
}
}
}
@@ -7994,11 +7239,7 @@
NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
mHiddenApiBlacklist.registerObserver();
- final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
- ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
- ActivityThread.currentApplication().getMainExecutor(),
- mPssDelayConfigListener);
+ mAppProfiler.retrieveSettings();
synchronized (this) {
mDebugApp = mOrigDebugApp = debugApp;
@@ -8017,7 +7258,6 @@
mUserController.setInitialConfig(userSwitchUiEnabled, maxRunningUsers,
delayUserDataLocking);
mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs;
- mPssDeferralTime = pssDeferralMs;
}
}
@@ -9007,7 +8247,7 @@
public int getMemoryTrimLevel() {
enforceNotIsolatedCaller("getMyMemoryState");
synchronized (this) {
- return mLastMemoryLevel;
+ return mAppProfiler.getLastMemoryLevelLocked();
}
}
@@ -10018,7 +9258,7 @@
needSep = mAppErrors.dumpLocked(fd, pw, needSep, dumpPackage);
needSep = mAtmInternal.dumpForProcesses(fd, pw, dumpAll, dumpPackage, dumpAppId, needSep,
- mTestPssMode, mWakefulness);
+ mAppProfiler.getTestPssModeLocked(), mWakefulness);
if (dumpAll && mProcessList.mPendingStarts.size() > 0) {
if (needSep) pw.println();
@@ -10062,35 +9302,7 @@
+ " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
}
}
- if (mMemWatchProcesses.getMap().size() > 0) {
- pw.println(" Mem watch processes:");
- final ArrayMap<String, SparseArray<Pair<Long, String>>> procs
- = mMemWatchProcesses.getMap();
- for (int i=0; i<procs.size(); i++) {
- final String proc = procs.keyAt(i);
- final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
- for (int j=0; j<uids.size(); j++) {
- if (needSep) {
- pw.println();
- needSep = false;
- }
- StringBuilder sb = new StringBuilder();
- sb.append(" ").append(proc).append('/');
- UserHandle.formatUid(sb, uids.keyAt(j));
- Pair<Long, String> val = uids.valueAt(j);
- sb.append(": "); DebugUtils.sizeValueToString(val.first, sb);
- if (val.second != null) {
- sb.append(", report to ").append(val.second);
- }
- pw.println(sb.toString());
- }
- }
- pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
- pw.print(" mMemWatchDumpUri="); pw.println(mMemWatchDumpUri);
- pw.print(" mMemWatchDumpPid="); pw.println(mMemWatchDumpPid);
- pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
- pw.print(" mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated);
- }
+ needSep = mAppProfiler.dumpMemWatchProcessesLocked(pw, needSep);
if (mTrackAllocationApp != null) {
if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
if (needSep) {
@@ -10100,29 +9312,7 @@
pw.println(" mTrackAllocationApp=" + mTrackAllocationApp);
}
}
- if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
- || (mProfileData.getProfilerInfo() != null &&
- (mProfileData.getProfilerInfo().profileFile != null
- || mProfileData.getProfilerInfo().profileFd != null))) {
- if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
- if (needSep) {
- pw.println();
- needSep = false;
- }
- pw.println(" mProfileApp=" + mProfileData.getProfileApp()
- + " mProfileProc=" + mProfileData.getProfileProc());
- if (mProfileData.getProfilerInfo() != null) {
- pw.println(" mProfileFile=" + mProfileData.getProfilerInfo().profileFile
- + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
- pw.println(" mSamplingInterval="
- + mProfileData.getProfilerInfo().samplingInterval +
- " mAutoStopProfiler="
- + mProfileData.getProfilerInfo().autoStopProfiler +
- " mStreamingOutput=" + mProfileData.getProfilerInfo().streamingOutput);
- pw.println(" mProfileType=" + mProfileType);
- }
- }
- }
+ needSep = mAppProfiler.dumpProfileDataLocked(pw, dumpPackage, needSep);
if (mNativeDebuggingApp != null) {
if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) {
if (needSep) {
@@ -10150,14 +9340,13 @@
pw.println("");
mOomAdjuster.dumpSequenceNumbersLocked(pw);
mOomAdjuster.dumpProcCountsLocked(pw);
- pw.println(" mAllowLowerMemLevel=" + mAllowLowerMemLevel
- + " mLastMemoryLevel=" + mLastMemoryLevel
- + " mLastNumProcesses=" + mLastNumProcesses);
+ mAppProfiler.dumpMemoryLevelsLocked(pw);
long now = SystemClock.uptimeMillis();
pw.print(" mLastIdleTime=");
TimeUtils.formatDuration(now, mLastIdleTime, pw);
pw.print(" mLowRamSinceLastIdle=");
- TimeUtils.formatDuration(getLowRamTimeSinceIdle(now), pw);
+ TimeUtils.formatDuration(
+ mAppProfiler.getLowRamTimeSinceIdleLocked(now), pw);
pw.println();
pw.println();
@@ -10305,7 +9494,8 @@
dumpPackage);
mAppErrors.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.APP_ERRORS,
dumpPackage);
- mAtmInternal.writeProcessesToProto(proto, dumpPackage, mWakefulness, mTestPssMode);
+ mAtmInternal.writeProcessesToProto(proto, dumpPackage, mWakefulness,
+ mAppProfiler.getTestPssModeLocked());
if (dumpPackage == null) {
mUserController.dumpDebug(proto,
@@ -10342,42 +9532,7 @@
}
}
- if (mMemWatchProcesses.getMap().size() > 0) {
- final long token = proto.start(ActivityManagerServiceDumpProcessesProto.MEM_WATCH_PROCESSES);
- ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap();
- for (int i=0; i<procs.size(); i++) {
- final String proc = procs.keyAt(i);
- final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
- final long ptoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.PROCS);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.NAME, proc);
- for (int j=0; j<uids.size(); j++) {
- final long utoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MEM_STATS);
- Pair<Long, String> val = uids.valueAt(j);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.UID, uids.keyAt(j));
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.SIZE,
- DebugUtils.sizeValueToString(val.first, new StringBuilder()));
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.MemStats.REPORT_TO, val.second);
- proto.end(utoken);
- }
- proto.end(ptoken);
- }
-
- final long dtoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME,
- mMemWatchDumpProcName);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI,
- mMemWatchDumpUri.toString());
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID,
- mMemWatchDumpPid);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID,
- mMemWatchDumpUid);
- proto.write(
- ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED,
- mMemWatchIsUserInitiated);
- proto.end(dtoken);
-
- proto.end(token);
- }
+ mAppProfiler.writeMemWatchProcessToProtoLocked(proto);
if (mTrackAllocationApp != null) {
if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
@@ -10386,25 +9541,7 @@
}
}
- if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
- || (mProfileData.getProfilerInfo() != null &&
- (mProfileData.getProfilerInfo().profileFile != null
- || mProfileData.getProfilerInfo().profileFd != null))) {
- if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
- final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE);
- proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME,
- mProfileData.getProfileApp());
- mProfileData.getProfileProc().dumpDebug(proto,
- ActivityManagerServiceDumpProcessesProto.Profile.PROC);
- if (mProfileData.getProfilerInfo() != null) {
- mProfileData.getProfilerInfo().dumpDebug(proto,
- ActivityManagerServiceDumpProcessesProto.Profile.INFO);
- proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE,
- mProfileType);
- }
- proto.end(token);
- }
- }
+ mAppProfiler.writeProfileDataToProtoLocked(proto, dumpPackage);
if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) {
proto.write(ActivityManagerServiceDumpProcessesProto.NATIVE_DEBUGGING_APP, mNativeDebuggingApp);
@@ -10422,12 +9559,11 @@
proto.write(ActivityManagerServiceDumpProcessesProto.BOOT_ANIMATION_COMPLETE, mBootAnimationComplete);
proto.write(ActivityManagerServiceDumpProcessesProto.LAST_POWER_CHECK_UPTIME_MS, mLastPowerCheckUptime);
mOomAdjuster.dumpProcessListVariablesLocked(proto);
- proto.write(ActivityManagerServiceDumpProcessesProto.ALLOW_LOWER_MEM_LEVEL, mAllowLowerMemLevel);
- proto.write(ActivityManagerServiceDumpProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel);
- proto.write(ActivityManagerServiceDumpProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses);
+ mAppProfiler.writeMemoryLevelsToProtoLocked(proto);
long now = SystemClock.uptimeMillis();
ProtoUtils.toDuration(proto, ActivityManagerServiceDumpProcessesProto.LAST_IDLE_TIME, mLastIdleTime, now);
- proto.write(ActivityManagerServiceDumpProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS, getLowRamTimeSinceIdle(now));
+ proto.write(ActivityManagerServiceDumpProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS,
+ mAppProfiler.getLowRamTimeSinceIdleLocked(now));
}
}
@@ -11610,7 +10746,7 @@
}
private final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
- MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
+ MemoryUsageDumpOptions opts, final String[] innerArgs, boolean brief,
ArrayList<ProcessRecord> procs, PrintWriter categoryPw) {
long uptime = SystemClock.uptimeMillis();
long realtime = SystemClock.elapsedRealtime();
@@ -11630,16 +10766,13 @@
findPid = Integer.parseInt(innerArgs[0]);
} catch (NumberFormatException e) {
}
- synchronized (mProcessCpuTracker) {
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (st.pid == findPid || (st.baseName != null
- && st.baseName.equals(innerArgs[0]))) {
- nativeProcs.add(st);
- }
+ final int fFindPid = findPid;
+ mAppProfiler.forAllCpuStats((st) -> {
+ if (st.pid == fFindPid || (st.baseName != null
+ && st.baseName.equals(innerArgs[0]))) {
+ nativeProcs.add(st);
}
- }
+ });
if (nativeProcs.size() > 0) {
dumpApplicationMemoryUsageHeader(pw, uptime, realtime,
opts.isCheckinRequest, opts.isCompact);
@@ -11697,21 +10830,13 @@
ArrayList<MemItem> procMems = new ArrayList<MemItem>();
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
- long nativePss = 0;
- long nativeSwapPss = 0;
- long nativeRss = 0;
- long dalvikPss = 0;
- long dalvikSwapPss = 0;
- long dalvikRss = 0;
+ final long[] ss = new long[INDEX_LAST];
long[] dalvikSubitemPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemSwapPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemRss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
- long otherPss = 0;
- long otherSwapPss = 0;
- long otherRss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
@@ -11722,7 +10847,6 @@
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
new ArrayList[DUMP_MEM_OOM_LABEL.length];
- long totalPss = 0;
long totalSwapPss = 0;
long totalRss = 0;
long cachedPss = 0;
@@ -11831,40 +10955,40 @@
}
if (!opts.isCheckinRequest && mi != null) {
- totalPss += myTotalPss;
- totalSwapPss += myTotalSwapPss;
- totalRss += myTotalRss;
+ ss[INDEX_TOTAL_PSS] += myTotalPss;
+ ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss;
+ ss[INDEX_TOTAL_RSS] += myTotalRss;
MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
(hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
myTotalSwapPss, myTotalRss, pid, hasActivities);
procMems.add(pssItem);
procMemsMap.put(pid, pssItem);
- nativePss += mi.nativePss;
- nativeSwapPss += mi.nativeSwappedOutPss;
- nativeRss += mi.nativeRss;
- dalvikPss += mi.dalvikPss;
- dalvikSwapPss += mi.dalvikSwappedOutPss;
- dalvikRss += mi.dalvikRss;
+ ss[INDEX_NATIVE_PSS] += mi.nativePss;
+ ss[INDEX_NATIVE_SWAP_PSS] += mi.nativeSwappedOutPss;
+ ss[INDEX_NATIVE_RSS] += mi.nativeRss;
+ ss[INDEX_DALVIK_PSS] += mi.dalvikPss;
+ ss[INDEX_DALVIK_SWAP_PSS] += mi.dalvikSwappedOutPss;
+ ss[INDEX_DALVIK_RSS] += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
- otherPss += mi.otherPss;
- otherRss += mi.otherRss;
- otherSwapPss += mi.otherSwappedOutPss;
+ ss[INDEX_OTHER_PSS] += mi.otherPss;
+ ss[INDEX_OTHER_RSS] += mi.otherRss;
+ ss[INDEX_OTHER_SWAP_PSS] += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
- otherPss -= mem;
+ ss[INDEX_OTHER_PSS] -= mem;
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
- otherSwapPss -= mem;
+ ss[INDEX_OTHER_SWAP_PSS] -= mem;
mem = mi.getOtherRss(j);
miscRss[j] += mem;
- otherRss -= mem;
+ ss[INDEX_OTHER_RSS] -= mem;
}
if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -11894,86 +11018,87 @@
if (collectNative) {
mi = null;
- synchronized (mProcessCpuTracker) {
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
- if (mi == null) {
- mi = new Debug.MemoryInfo();
- }
- if (!brief && !opts.oomOnly) {
- if (!Debug.getMemoryInfo(st.pid, mi)) {
- continue;
- }
- } else {
- long pss = Debug.getPss(st.pid, tmpLong, null);
- if (pss == 0) {
- continue;
- }
- mi.nativePss = (int) pss;
- mi.nativePrivateDirty = (int) tmpLong[0];
- mi.nativeRss = (int) tmpLong[2];
- }
-
- final long myTotalPss = mi.getTotalPss();
- final long myTotalSwapPss = mi.getTotalSwappedOutPss();
- final long myTotalRss = mi.getTotalRss();
- totalPss += myTotalPss;
- totalSwapPss += myTotalSwapPss;
- totalRss += myTotalRss;
- nativeProcTotalPss += myTotalPss;
-
- MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
- st.name, myTotalPss, mi.getSummaryTotalSwapPss(), myTotalRss,
- st.pid, false);
- procMems.add(pssItem);
-
- nativePss += mi.nativePss;
- nativeSwapPss += mi.nativeSwappedOutPss;
- nativeRss += mi.nativeRss;
- dalvikPss += mi.dalvikPss;
- dalvikSwapPss += mi.dalvikSwappedOutPss;
- dalvikRss += mi.dalvikRss;
- for (int j=0; j<dalvikSubitemPss.length; j++) {
- dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikSubitemSwapPss[j] +=
- mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
- + j);
- }
- otherPss += mi.otherPss;
- otherSwapPss += mi.otherSwappedOutPss;
- otherRss += mi.otherRss;
- for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
- long mem = mi.getOtherPss(j);
- miscPss[j] += mem;
- otherPss -= mem;
- mem = mi.getOtherSwappedOutPss(j);
- miscSwapPss[j] += mem;
- otherSwapPss -= mem;
- mem = mi.getOtherRss(j);
- miscRss[j] += mem;
- otherRss -= mem;
- }
- oomPss[0] += myTotalPss;
- oomSwapPss[0] += myTotalSwapPss;
- if (oomProcs[0] == null) {
- oomProcs[0] = new ArrayList<MemItem>();
- }
- oomProcs[0].add(pssItem);
- oomRss[0] += myTotalRss;
+ final Debug.MemoryInfo[] memInfos = new Debug.MemoryInfo[1];
+ mAppProfiler.forAllCpuStats((st) -> {
+ if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
+ if (memInfos[0] == null) {
+ memInfos[0] = new Debug.MemoryInfo();
}
+ final Debug.MemoryInfo info = memInfos[0];
+ if (!brief && !opts.oomOnly) {
+ if (!Debug.getMemoryInfo(st.pid, info)) {
+ return;
+ }
+ } else {
+ long pss = Debug.getPss(st.pid, tmpLong, null);
+ if (pss == 0) {
+ return;
+ }
+ info.nativePss = (int) pss;
+ info.nativePrivateDirty = (int) tmpLong[0];
+ info.nativeRss = (int) tmpLong[2];
+ }
+
+ final long myTotalPss = info.getTotalPss();
+ final long myTotalSwapPss = info.getTotalSwappedOutPss();
+ final long myTotalRss = info.getTotalRss();
+ ss[INDEX_TOTAL_PSS] += myTotalPss;
+ ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss;
+ ss[INDEX_TOTAL_RSS] += myTotalRss;
+ ss[INDEX_TOTAL_NATIVE_PSS] += myTotalPss;
+
+ MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
+ st.name, myTotalPss, info.getSummaryTotalSwapPss(), myTotalRss,
+ st.pid, false);
+ procMems.add(pssItem);
+
+ ss[INDEX_NATIVE_PSS] += info.nativePss;
+ ss[INDEX_NATIVE_SWAP_PSS] += info.nativeSwappedOutPss;
+ ss[INDEX_NATIVE_RSS] += info.nativeRss;
+ ss[INDEX_DALVIK_PSS] += info.dalvikPss;
+ ss[INDEX_DALVIK_SWAP_PSS] += info.dalvikSwappedOutPss;
+ ss[INDEX_DALVIK_RSS] += info.dalvikRss;
+ for (int j = 0; j < dalvikSubitemPss.length; j++) {
+ dalvikSubitemPss[j] += info.getOtherPss(
+ Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemSwapPss[j] +=
+ info.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += info.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
+ + j);
+ }
+ ss[INDEX_OTHER_PSS] += info.otherPss;
+ ss[INDEX_OTHER_SWAP_PSS] += info.otherSwappedOutPss;
+ ss[INDEX_OTHER_RSS] += info.otherRss;
+ for (int j = 0; j < Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
+ long mem = info.getOtherPss(j);
+ miscPss[j] += mem;
+ ss[INDEX_OTHER_PSS] -= mem;
+ mem = info.getOtherSwappedOutPss(j);
+ miscSwapPss[j] += mem;
+ ss[INDEX_OTHER_SWAP_PSS] -= mem;
+ mem = info.getOtherRss(j);
+ miscRss[j] += mem;
+ ss[INDEX_OTHER_RSS] -= mem;
+ }
+ oomPss[0] += myTotalPss;
+ oomSwapPss[0] += myTotalSwapPss;
+ if (oomProcs[0] == null) {
+ oomProcs[0] = new ArrayList<MemItem>();
+ }
+ oomProcs[0].add(pssItem);
+ oomRss[0] += myTotalRss;
}
- }
+ });
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
- catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, nativeRss, -1));
+ catMems.add(new MemItem("Native", "Native",
+ ss[INDEX_NATIVE_PSS], ss[INDEX_NATIVE_SWAP_PSS], ss[INDEX_NATIVE_RSS], -1));
final int dalvikId = -2;
- catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikRss,
- dalvikId));
- catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, otherRss, -3));
+ catMems.add(new MemItem("Dalvik", "Dalvik", ss[INDEX_DALVIK_PSS],
+ ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], dalvikId));
+ catMems.add(new MemItem("Unknown", "Unknown", ss[INDEX_OTHER_PSS],
+ ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j));
@@ -12039,7 +11164,7 @@
}
dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, false, false);
}
- opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && totalSwapPss != 0;
+ opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && ss[INDEX_TOTAL_SWAP_PSS] != 0;
if (!brief && !opts.oomOnly && !opts.isCompact) {
pw.println();
pw.println("Total PSS by process:");
@@ -12065,40 +11190,23 @@
}
MemInfoReader memInfo = new MemInfoReader();
memInfo.readMemInfo();
- if (nativeProcTotalPss > 0) {
+ if (ss[INDEX_TOTAL_NATIVE_PSS] > 0) {
synchronized (mProcessStats.mLock) {
final long cachedKb = memInfo.getCachedSizeKb();
final long freeKb = memInfo.getFreeSizeKb();
final long zramKb = memInfo.getZramTotalSizeKb();
final long kernelKb = memInfo.getKernelUsedSizeKb();
- EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
- kernelKb*1024, nativeProcTotalPss*1024);
+ EventLogTags.writeAmMeminfo(cachedKb * 1024, freeKb * 1024, zramKb * 1024,
+ kernelKb * 1024, ss[INDEX_TOTAL_NATIVE_PSS] * 1024);
mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
- nativeProcTotalPss);
+ ss[INDEX_TOTAL_NATIVE_PSS]);
}
}
if (!brief) {
if (!opts.isCompact) {
pw.print("Total RAM: "); pw.print(stringifyKBSize(memInfo.getTotalSizeKb()));
pw.print(" (status ");
- switch (mLastMemoryLevel) {
- case ProcessStats.ADJ_MEM_FACTOR_NORMAL:
- pw.println("normal)");
- break;
- case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
- pw.println("moderate)");
- break;
- case ProcessStats.ADJ_MEM_FACTOR_LOW:
- pw.println("low)");
- break;
- case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
- pw.println("critical)");
- break;
- default:
- pw.print(mLastMemoryLevel);
- pw.println(")");
- break;
- }
+ mAppProfiler.dumpLastMemoryLevelLocked(pw);
pw.print(" Free RAM: ");
pw.print(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
+ memInfo.getFreeSizeKb()));
@@ -12113,7 +11221,7 @@
pw.print("ram,"); pw.print(memInfo.getTotalSizeKb()); pw.print(",");
pw.print(cachedPss + memInfo.getCachedSizeKb()
+ memInfo.getFreeSizeKb()); pw.print(",");
- pw.println(totalPss - cachedPss);
+ pw.println(ss[INDEX_TOTAL_PSS] - cachedPss);
}
}
long kernelUsed = memInfo.getKernelUsedSizeKb();
@@ -12135,13 +11243,14 @@
// set on ION VMAs, therefore consider the entire ION heap as used kernel memory
kernelUsed += ionHeap;
}
- final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
+ final long lostRAM = memInfo.getTotalSizeKb()
+ - (ss[INDEX_TOTAL_PSS] - ss[INDEX_TOTAL_SWAP_PSS])
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
if (!opts.isCompact) {
- pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
+ pw.print(" Used RAM: "); pw.print(stringifyKBSize(ss[INDEX_TOTAL_PSS] - cachedPss
+ kernelUsed)); pw.print(" (");
- pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + ");
+ pw.print(stringifyKBSize(ss[INDEX_TOTAL_PSS] - cachedPss)); pw.print(" used pss + ");
pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n");
pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM));
} else {
@@ -12215,7 +11324,7 @@
}
private final void dumpApplicationMemoryUsage(FileDescriptor fd,
- MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
+ MemoryUsageDumpOptions opts, final String[] innerArgs, boolean brief,
ArrayList<ProcessRecord> procs) {
final long uptimeMs = SystemClock.uptimeMillis();
final long realtimeMs = SystemClock.elapsedRealtime();
@@ -12227,7 +11336,7 @@
if (innerArgs.length > 0) {
proc = innerArgs[0];
if (proc.charAt(0) != '-') {
- ArrayList<ProcessCpuTracker.Stats> nativeProcs
+ final ArrayList<ProcessCpuTracker.Stats> nativeProcs
= new ArrayList<ProcessCpuTracker.Stats>();
updateCpuStatsNow();
int findPid = -1;
@@ -12235,16 +11344,13 @@
findPid = Integer.parseInt(innerArgs[0]);
} catch (NumberFormatException e) {
}
- synchronized (mProcessCpuTracker) {
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (st.pid == findPid || (st.baseName != null
- && st.baseName.equals(innerArgs[0]))) {
- nativeProcs.add(st);
- }
+ final int fFindPid = findPid;
+ mAppProfiler.forAllCpuStats((st) -> {
+ if (st.pid == fFindPid || (st.baseName != null
+ && st.baseName.equals(innerArgs[0]))) {
+ nativeProcs.add(st);
}
- }
+ });
if (nativeProcs.size() > 0) {
ProtoOutputStream proto = new ProtoOutputStream(fd);
@@ -12308,36 +11414,25 @@
proto.write(MemInfoDumpProto.UPTIME_DURATION_MS, uptimeMs);
proto.write(MemInfoDumpProto.ELAPSED_REALTIME_MS, realtimeMs);
- ArrayList<MemItem> procMems = new ArrayList<MemItem>();
+ final ArrayList<MemItem> procMems = new ArrayList<MemItem>();
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
- long nativePss = 0;
- long nativeSwapPss = 0;
- long nativeRss = 0;
- long dalvikPss = 0;
- long dalvikSwapPss = 0;
- long dalvikRss = 0;
+ final long[] ss = new long[INDEX_LAST];
long[] dalvikSubitemPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemSwapPss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
long[] dalvikSubitemRss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
- long otherPss = 0;
- long otherSwapPss = 0;
- long otherRss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
- long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
- long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length];
- long[] oomRss = new long[DUMP_MEM_OOM_LABEL.length];
- ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
+ final long[] oomPss = new long[DUMP_MEM_OOM_LABEL.length];
+ final long[] oomSwapPss = new long[DUMP_MEM_OOM_LABEL.length];
+ final long[] oomRss = new long[DUMP_MEM_OOM_LABEL.length];
+ final ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
new ArrayList[DUMP_MEM_OOM_LABEL.length];
- long totalPss = 0;
- long totalSwapPss = 0;
- long totalRss = 0;
long cachedPss = 0;
long cachedSwapPss = 0;
boolean hasSwapPss = false;
@@ -12438,40 +11533,40 @@
}
if (!opts.isCheckinRequest && mi != null) {
- totalPss += myTotalPss;
- totalSwapPss += myTotalSwapPss;
- totalRss += myTotalRss;
+ ss[INDEX_TOTAL_PSS] += myTotalPss;
+ ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss;
+ ss[INDEX_TOTAL_RSS] += myTotalRss;
MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
(hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
myTotalSwapPss, myTotalRss, pid, hasActivities);
procMems.add(pssItem);
procMemsMap.put(pid, pssItem);
- nativePss += mi.nativePss;
- nativeSwapPss += mi.nativeSwappedOutPss;
- nativeRss += mi.nativeRss;
- dalvikPss += mi.dalvikPss;
- dalvikSwapPss += mi.dalvikSwappedOutPss;
- dalvikRss += mi.dalvikRss;
+ ss[INDEX_NATIVE_PSS] += mi.nativePss;
+ ss[INDEX_NATIVE_SWAP_PSS] += mi.nativeSwappedOutPss;
+ ss[INDEX_NATIVE_RSS] += mi.nativeRss;
+ ss[INDEX_DALVIK_PSS] += mi.dalvikPss;
+ ss[INDEX_DALVIK_SWAP_PSS] += mi.dalvikSwappedOutPss;
+ ss[INDEX_DALVIK_RSS] += mi.dalvikRss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemSwapPss[j] +=
mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
- otherPss += mi.otherPss;
- otherRss += mi.otherRss;
- otherSwapPss += mi.otherSwappedOutPss;
+ ss[INDEX_OTHER_PSS] += mi.otherPss;
+ ss[INDEX_OTHER_RSS] += mi.otherRss;
+ ss[INDEX_OTHER_SWAP_PSS] += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
- otherPss -= mem;
+ ss[INDEX_OTHER_PSS] -= mem;
mem = mi.getOtherSwappedOutPss(j);
miscSwapPss[j] += mem;
- otherSwapPss -= mem;
+ ss[INDEX_OTHER_SWAP_PSS] -= mem;
mem = mi.getOtherRss(j);
miscRss[j] += mem;
- otherRss -= mem;
+ ss[INDEX_OTHER_RSS] -= mem;
}
if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -12500,86 +11595,87 @@
if (collectNative) {
mi = null;
- synchronized (mProcessCpuTracker) {
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
- if (mi == null) {
- mi = new Debug.MemoryInfo();
- }
- if (!brief && !opts.oomOnly) {
- if (!Debug.getMemoryInfo(st.pid, mi)) {
- continue;
- }
- } else {
- long pss = Debug.getPss(st.pid, tmpLong, null);
- if (pss == 0) {
- continue;
- }
- mi.nativePss = (int) pss;
- mi.nativePrivateDirty = (int) tmpLong[0];
- mi.nativeRss = (int) tmpLong[2];
- }
-
- final long myTotalPss = mi.getTotalPss();
- final long myTotalSwapPss = mi.getTotalSwappedOutPss();
- final long myTotalRss = mi.getTotalRss();
- totalPss += myTotalPss;
- totalSwapPss += myTotalSwapPss;
- totalRss += myTotalRss;
- nativeProcTotalPss += myTotalPss;
-
- MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
- st.name, myTotalPss, mi.getSummaryTotalSwapPss(), myTotalRss,
- st.pid, false);
- procMems.add(pssItem);
-
- nativePss += mi.nativePss;
- nativeSwapPss += mi.nativeSwappedOutPss;
- nativeRss += mi.nativeRss;
- dalvikPss += mi.dalvikPss;
- dalvikSwapPss += mi.dalvikSwappedOutPss;
- dalvikRss += mi.dalvikRss;
- for (int j=0; j<dalvikSubitemPss.length; j++) {
- dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikSubitemSwapPss[j] +=
- mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
- + j);
- }
- otherPss += mi.otherPss;
- otherSwapPss += mi.otherSwappedOutPss;
- otherRss += mi.otherRss;
- for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
- long mem = mi.getOtherPss(j);
- miscPss[j] += mem;
- otherPss -= mem;
- mem = mi.getOtherSwappedOutPss(j);
- miscSwapPss[j] += mem;
- otherSwapPss -= mem;
- mem = mi.getOtherRss(j);
- miscRss[j] += mem;
- otherRss -= mem;
- }
- oomPss[0] += myTotalPss;
- oomSwapPss[0] += myTotalSwapPss;
- if (oomProcs[0] == null) {
- oomProcs[0] = new ArrayList<MemItem>();
- }
- oomProcs[0].add(pssItem);
- oomRss[0] += myTotalRss;
+ final Debug.MemoryInfo[] memInfos = new Debug.MemoryInfo[1];
+ mAppProfiler.forAllCpuStats((st) -> {
+ if (st.vsize > 0 && procMemsMap.indexOfKey(st.pid) < 0) {
+ if (memInfos[0] == null) {
+ memInfos[0] = new Debug.MemoryInfo();
}
+ final Debug.MemoryInfo info = memInfos[0];
+ if (!brief && !opts.oomOnly) {
+ if (!Debug.getMemoryInfo(st.pid, info)) {
+ return;
+ }
+ } else {
+ long pss = Debug.getPss(st.pid, tmpLong, null);
+ if (pss == 0) {
+ return;
+ }
+ info.nativePss = (int) pss;
+ info.nativePrivateDirty = (int) tmpLong[0];
+ info.nativeRss = (int) tmpLong[2];
+ }
+
+ final long myTotalPss = info.getTotalPss();
+ final long myTotalSwapPss = info.getTotalSwappedOutPss();
+ final long myTotalRss = info.getTotalRss();
+ ss[INDEX_TOTAL_PSS] += myTotalPss;
+ ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss;
+ ss[INDEX_TOTAL_RSS] += myTotalRss;
+ ss[INDEX_TOTAL_NATIVE_PSS] += myTotalPss;
+
+ MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
+ st.name, myTotalPss, info.getSummaryTotalSwapPss(), myTotalRss,
+ st.pid, false);
+ procMems.add(pssItem);
+
+ ss[INDEX_NATIVE_PSS] += info.nativePss;
+ ss[INDEX_NATIVE_SWAP_PSS] += info.nativeSwappedOutPss;
+ ss[INDEX_NATIVE_RSS] += info.nativeRss;
+ ss[INDEX_DALVIK_PSS] += info.dalvikPss;
+ ss[INDEX_DALVIK_SWAP_PSS] += info.dalvikSwappedOutPss;
+ ss[INDEX_DALVIK_RSS] += info.dalvikRss;
+ for (int j = 0; j < dalvikSubitemPss.length; j++) {
+ dalvikSubitemPss[j] += info.getOtherPss(
+ Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemSwapPss[j] +=
+ info.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemRss[j] += info.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS
+ + j);
+ }
+ ss[INDEX_OTHER_PSS] += info.otherPss;
+ ss[INDEX_OTHER_SWAP_PSS] += info.otherSwappedOutPss;
+ ss[INDEX_OTHER_RSS] += info.otherRss;
+ for (int j = 0; j < Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
+ long mem = info.getOtherPss(j);
+ miscPss[j] += mem;
+ ss[INDEX_OTHER_PSS] -= mem;
+ mem = info.getOtherSwappedOutPss(j);
+ miscSwapPss[j] += mem;
+ ss[INDEX_OTHER_SWAP_PSS] -= mem;
+ mem = info.getOtherRss(j);
+ miscRss[j] += mem;
+ ss[INDEX_OTHER_RSS] -= mem;
+ }
+ oomPss[0] += myTotalPss;
+ oomSwapPss[0] += myTotalSwapPss;
+ if (oomProcs[0] == null) {
+ oomProcs[0] = new ArrayList<MemItem>();
+ }
+ oomProcs[0].add(pssItem);
+ oomRss[0] += myTotalRss;
}
- }
+ });
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
- catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, nativeRss, -1));
+ catMems.add(new MemItem("Native", "Native", ss[INDEX_NATIVE_PSS],
+ ss[INDEX_NATIVE_SWAP_PSS], ss[INDEX_NATIVE_RSS], -1));
final int dalvikId = -2;
- catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, dalvikRss,
- dalvikId));
- catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, otherRss, -3));
+ catMems.add(new MemItem("Dalvik", "Dalvik", ss[INDEX_DALVIK_PSS],
+ ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], dalvikId));
+ catMems.add(new MemItem("Unknown", "Unknown", ss[INDEX_OTHER_PSS],
+ ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j));
@@ -12636,7 +11732,7 @@
catMems, true, false, false);
}
- opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && totalSwapPss != 0;
+ opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && ss[INDEX_TOTAL_SWAP_PSS] != 0;
if (!opts.oomOnly) {
dumpMemItems(proto, MemInfoDumpProto.TOTAL_PSS_BY_PROCESS, "proc",
procMems, true, true, opts.dumpSwapPss);
@@ -12649,29 +11745,30 @@
}
MemInfoReader memInfo = new MemInfoReader();
memInfo.readMemInfo();
- if (nativeProcTotalPss > 0) {
+ if (ss[INDEX_TOTAL_NATIVE_PSS] > 0) {
synchronized (mProcessStats.mLock) {
final long cachedKb = memInfo.getCachedSizeKb();
final long freeKb = memInfo.getFreeSizeKb();
final long zramKb = memInfo.getZramTotalSizeKb();
final long kernelKb = memInfo.getKernelUsedSizeKb();
- EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
- kernelKb*1024, nativeProcTotalPss*1024);
+ EventLogTags.writeAmMeminfo(cachedKb * 1024, freeKb * 1024, zramKb * 1024,
+ kernelKb * 1024, ss[INDEX_TOTAL_NATIVE_PSS] * 1024);
mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
- nativeProcTotalPss);
+ ss[INDEX_TOTAL_NATIVE_PSS]);
}
}
if (!brief) {
proto.write(MemInfoDumpProto.TOTAL_RAM_KB, memInfo.getTotalSizeKb());
- proto.write(MemInfoDumpProto.STATUS, mLastMemoryLevel);
+ proto.write(MemInfoDumpProto.STATUS, mAppProfiler.getLastMemoryLevelLocked());
proto.write(MemInfoDumpProto.CACHED_PSS_KB, cachedPss);
proto.write(MemInfoDumpProto.CACHED_KERNEL_KB, memInfo.getCachedSizeKb());
proto.write(MemInfoDumpProto.FREE_KB, memInfo.getFreeSizeKb());
}
- long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
+ long lostRAM = memInfo.getTotalSizeKb()
+ - (ss[INDEX_TOTAL_PSS] - ss[INDEX_TOTAL_SWAP_PSS])
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
- proto.write(MemInfoDumpProto.USED_PSS_KB, totalPss - cachedPss);
+ proto.write(MemInfoDumpProto.USED_PSS_KB, ss[INDEX_TOTAL_PSS] - cachedPss);
proto.write(MemInfoDumpProto.USED_KERNEL_KB, memInfo.getKernelUsedSizeKb());
proto.write(MemInfoDumpProto.LOST_RAM_KB, lostRAM);
if (!brief) {
@@ -12742,13 +11839,8 @@
updateCpuStatsNow();
long[] memtrackTmp = new long[1];
long[] swaptrackTmp = new long[2];
- final List<ProcessCpuTracker.Stats> stats;
// Get a list of Stats that have vsize > 0
- synchronized (mProcessCpuTracker) {
- stats = mProcessCpuTracker.getStats((st) -> {
- return st.vsize > 0;
- });
- }
+ final List<ProcessCpuTracker.Stats> stats = mAppProfiler.getCpuStats(st -> st.vsize > 0);
final int statsCount = stats.size();
for (int i = 0; i < statsCount; i++) {
ProcessCpuTracker.Stats st = stats.get(i);
@@ -13043,8 +12135,7 @@
}
mProcessesToGc.remove(app);
- mPendingPssProcesses.remove(app);
- ProcessList.abortNextPssTime(app.procStateMemTracker);
+ mAppProfiler.onCleanupApplicationRecordLocked(app);
// Dismiss any open dialogs.
app.getDialogController().clearAllErrorDialogs();
@@ -14582,10 +13673,7 @@
timeFormatPreferenceMsgValue, 0);
mHandler.sendMessage(updateTimePreferenceMsg);
}
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- stats.noteCurrentTimeChangedLocked();
- }
+ mBatteryStatsService.noteCurrentTimeChanged();
break;
case Intent.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
@@ -15385,8 +14473,8 @@
}
@Override
- public StackInfo getFocusedStackInfo() throws RemoteException {
- return mActivityTaskManager.getFocusedStackInfo();
+ public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException {
+ return mActivityTaskManager.getFocusedRootTaskInfo();
}
@Override
@@ -15598,229 +14686,6 @@
}
}
- /** @hide */
- public static Uri makeHeapDumpUri(String procName) {
- return Uri.parse("content://com.android.shell.heapdump/" + procName + "_javaheap.bin");
- }
-
- private final class RecordPssRunnable implements Runnable {
- private final ProcessRecord mProc;
- private final Uri mDumpUri;
- private final ContentResolver mContentResolver;
-
- RecordPssRunnable(ProcessRecord proc, Uri dumpUri, ContentResolver contentResolver) {
- mProc = proc;
- mDumpUri = dumpUri;
- mContentResolver = contentResolver;
- }
-
- @Override
- public void run() {
- try (ParcelFileDescriptor fd = mContentResolver.openFileDescriptor(mDumpUri, "rw")) {
- IApplicationThread thread = mProc.thread;
- if (thread != null) {
- try {
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "Requesting dump heap from "
- + mProc + " to " + mDumpUri.getPath());
- }
- thread.dumpHeap(/* managed= */ true,
- /* mallocInfo= */ false, /* runGc= */ false,
- mDumpUri.getPath(), fd,
- /* finishCallback= */ null);
- } catch (RemoteException e) {
- }
- }
- } catch (IOException e) {
- Slog.e(TAG, "Failed to dump heap", e);
- // Need to clear the heap dump variables, otherwise no further heap dumps will be
- // attempted.
- abortHeapDump(mProc.processName);
- }
- }
- }
-
- /**
- * Record new PSS sample for a process.
- */
- void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
- long rss, int statType, long pssDuration, long now) {
- EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
- swapPss * 1024, rss * 1024, statType, procState, pssDuration);
- proc.lastPssTime = now;
- synchronized (mProcessStats.mLock) {
- proc.baseProcessTracker.addPss(
- pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
- }
- for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) {
- ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
- proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
- pss, uss, rss, statType, pssDuration,
- holder.appVersion);
- }
- if (DEBUG_PSS) Slog.d(TAG_PSS,
- "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
- + " state=" + ProcessList.makeProcStateString(procState));
- if (proc.initialIdlePss == 0) {
- proc.initialIdlePss = pss;
- }
- proc.lastPss = pss;
- proc.lastSwapPss = swapPss;
- if (procState >= ActivityManager.PROCESS_STATE_HOME) {
- proc.lastCachedPss = pss;
- proc.lastCachedSwapPss = swapPss;
- }
- proc.mLastRss = rss;
-
- final SparseArray<Pair<Long, String>> watchUids
- = mMemWatchProcesses.getMap().get(proc.processName);
- Long check = null;
- if (watchUids != null) {
- Pair<Long, String> val = watchUids.get(proc.uid);
- if (val == null) {
- val = watchUids.get(0);
- }
- if (val != null) {
- check = val.first;
- }
- }
- if (check != null) {
- if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
- if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- isDebuggable = true;
- }
- }
- if (isDebuggable) {
- Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting");
- startHeapDumpLocked(proc, false);
- } else {
- Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check
- + ", but debugging not enabled");
- }
- }
- }
- }
-
- private void startHeapDumpLocked(ProcessRecord proc, boolean isUserInitiated) {
- mMemWatchDumpProcName = proc.processName;
- mMemWatchDumpUri = makeHeapDumpUri(proc.processName);
- mMemWatchDumpPid = proc.pid;
- mMemWatchDumpUid = proc.uid;
- mMemWatchIsUserInitiated = isUserInitiated;
- Context ctx;
- try {
- ctx = mContext.createPackageContextAsUser("android", 0,
- UserHandle.getUserHandleForUid(mMemWatchDumpUid));
- } catch (NameNotFoundException e) {
- throw new RuntimeException("android package not found.");
- }
- BackgroundThread.getHandler().post(
- new RecordPssRunnable(proc, mMemWatchDumpUri, ctx.getContentResolver()));
- }
-
- /**
- * Schedule PSS collection of a process.
- */
- boolean requestPssLocked(ProcessRecord proc, int procState) {
- if (mPendingPssProcesses.contains(proc)) {
- return false;
- }
- if (mPendingPssProcesses.size() == 0) {
- final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0)
- ? mPssDeferralTime : 0;
- if (DEBUG_PSS && deferral > 0) {
- Slog.d(TAG_PSS, "requestPssLocked() deferring PSS request by "
- + deferral + " ms");
- }
- mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, deferral);
- }
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
- proc.pssProcState = procState;
- proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE;
- mPendingPssProcesses.add(proc);
- return true;
- }
-
- /**
- * Re-defer a posted PSS collection pass, if one exists. Assumes deferral is
- * currently active policy when called.
- */
- private void deferPssIfNeededLocked() {
- if (mPendingPssProcesses.size() > 0) {
- mBgHandler.removeMessages(COLLECT_PSS_BG_MSG);
- mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, mPssDeferralTime);
- }
- }
-
- private void deferPssForActivityStart() {
- synchronized (ActivityManagerService.this) {
- if (mPssDeferralTime > 0) {
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "Deferring PSS collection for activity start");
- }
- deferPssIfNeededLocked();
- mActivityStartingNesting.getAndIncrement();
- mBgHandler.sendEmptyMessageDelayed(STOP_DEFERRING_PSS_MSG, mPssDeferralTime);
- }
- }
- }
-
- /**
- * Schedule PSS collection of all processes.
- */
- void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
- if (!always) {
- if (now < (mLastFullPssTime +
- (memLowered ? mConstants.FULL_PSS_LOWERED_INTERVAL
- : mConstants.FULL_PSS_MIN_INTERVAL))) {
- return;
- }
- }
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of all procs! memLowered=" + memLowered);
- mLastFullPssTime = now;
- mFullPssPending = true;
- for (int i = mPendingPssProcesses.size() - 1; i >= 0; i--) {
- ProcessList.abortNextPssTime(mPendingPssProcesses.get(i).procStateMemTracker);;
- }
- mPendingPssProcesses.ensureCapacity(mProcessList.getLruSizeLocked());
- mPendingPssProcesses.clear();
- for (int i = mProcessList.getLruSizeLocked() - 1; i >= 0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (app.thread == null || app.getCurProcState() == PROCESS_STATE_NONEXISTENT) {
- continue;
- }
- if (memLowered || (always && now >
- app.lastStateTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
- || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
- app.pssProcState = app.setProcState;
- app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
- : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
- app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(),
- app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now);
- mPendingPssProcesses.add(app);
- }
- }
- if (!mBgHandler.hasMessages(COLLECT_PSS_BG_MSG)) {
- mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
- }
- }
-
- public void setTestPssMode(boolean enabled) {
- synchronized (this) {
- mTestPssMode = enabled;
- if (enabled) {
- // Whenever we enable the mode, we want to take a snapshot all of current
- // process mem use.
- requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, true);
- }
- }
- }
-
/**
* Ask a given process to GC right now.
*/
@@ -15957,7 +14822,6 @@
updateCpuStatsNow();
synchronized (this) {
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
boolean doCpuKills = true;
if (mLastPowerCheckUptime == 0) {
doCpuKills = false;
@@ -16004,10 +14868,8 @@
cpuLimit = mConstants.POWER_CHECK_MAX_CPU_4;
}
if (((cputimeUsed * 100) / uptimeSince) >= cpuLimit) {
- synchronized (stats) {
- stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
+ mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName,
uptimeSince, cputimeUsed);
- }
app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
+ " dur=" + checkDur + " limit=" + cpuLimit,
ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
@@ -16179,187 +15041,6 @@
}
@GuardedBy("this")
- final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
- final int N = mProcessList.getLruSizeLocked();
- final long now = SystemClock.uptimeMillis();
- int memFactor;
- if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
- memFactor = mLowMemDetector.getMemFactor();
- } else {
- // Now determine the memory trimming level of background processes.
- // Unfortunately we need to start at the back of the list to do this
- // properly. We only do this if the number of background apps we
- // are managing to keep around is less than half the maximum we desire;
- // if we are keeping a good number around, we'll let them use whatever
- // memory they want.
- if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
- && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
- final int numCachedAndEmpty = numCached + numEmpty;
- if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
- } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
- } else {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
- }
- } else {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
- }
- }
- // We always allow the memory level to go up (better). We only allow it to go
- // down if we are in a state where that is allowed, *and* the total number of processes
- // has gone down since last time.
- if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
- + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
- + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
- if (memFactor > mLastMemoryLevel) {
- if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
- memFactor = mLastMemoryLevel;
- if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
- }
- }
- if (memFactor != mLastMemoryLevel) {
- EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
- FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
- }
- mLastMemoryLevel = memFactor;
- mLastNumProcesses = mProcessList.getLruSizeLocked();
- boolean allChanged;
- int trackerMemFactor;
- synchronized (mProcessStats.mLock) {
- allChanged = mProcessStats.setMemFactorLocked(
- memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
- trackerMemFactor = mProcessStats.getMemFactorLocked();
- }
- if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
- if (mLowRamStartTime == 0) {
- mLowRamStartTime = now;
- }
- int step = 0;
- int fgTrimLevel;
- switch (memFactor) {
- case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
- break;
- case ProcessStats.ADJ_MEM_FACTOR_LOW:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
- break;
- default:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
- break;
- }
- int factor = numTrimming/3;
- int minFactor = 2;
- if (mAtmInternal.getHomeProcess() != null) minFactor++;
- if (mAtmInternal.getPreviousProcess() != null) minFactor++;
- if (factor < minFactor) factor = minFactor;
- int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
- for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (allChanged || app.procStateChanged) {
- setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
- }
- if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedByAm) {
- if (app.trimMemoryLevel < curLevel && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of " + app.processName + " to " + curLevel);
- app.thread.scheduleTrimMemory(curLevel);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = curLevel;
- step++;
- if (step >= factor) {
- step = 0;
- switch (curLevel) {
- case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
- break;
- case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
- break;
- }
- }
- } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- && !app.killedByAm) {
- if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
- && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of heavy-weight " + app.processName
- + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
- } else {
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && app.hasPendingUiClean()) {
- // If this application is now in the background and it
- // had done UI, then give it the special trim level to
- // have it free UI resources.
- final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
- if (app.trimMemoryLevel < level && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of bg-ui " + app.processName
- + " to " + level);
- app.thread.scheduleTrimMemory(level);
- } catch (RemoteException e) {
- }
- }
- app.setPendingUiClean(false);
- }
- if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of fg " + app.processName
- + " to " + fgTrimLevel);
- app.thread.scheduleTrimMemory(fgTrimLevel);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = fgTrimLevel;
- }
- }
- } else {
- if (mLowRamStartTime != 0) {
- mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
- mLowRamStartTime = 0;
- }
- for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (allChanged || app.procStateChanged) {
- setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
- }
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && app.hasPendingUiClean()) {
- if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
- && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of ui hidden " + app.processName
- + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
- } catch (RemoteException e) {
- }
- }
- app.setPendingUiClean(false);
- }
- app.trimMemoryLevel = 0;
- }
- }
- return allChanged;
- }
-
- @GuardedBy("this")
final void updateOomAdjLocked(String oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(oomAdjReason);
}
@@ -16647,109 +15328,31 @@
}
}
- private void stopProfilerLocked(ProcessRecord proc, int profileType) {
- if (proc == null || proc == mProfileData.getProfileProc()) {
- proc = mProfileData.getProfileProc();
- profileType = mProfileType;
- clearProfilerLocked();
- }
- if (proc == null) {
- return;
- }
- try {
- proc.thread.profilerControl(false, null, profileType);
- } catch (RemoteException e) {
- throw new IllegalStateException("Process disappeared");
- }
- }
-
- void clearProfilerLocked() {
- if (mProfileData.getProfilerInfo() != null
- && mProfileData.getProfilerInfo().profileFd != null) {
- try {
- mProfileData.getProfilerInfo().profileFd.close();
- } catch (IOException e) {
- }
- }
- mProfileData.setProfileApp(null);
- mProfileData.setProfileProc(null);
- mProfileData.setProfilerInfo(null);
- }
-
public boolean profileControl(String process, int userId, boolean start,
ProfilerInfo profilerInfo, int profileType) throws RemoteException {
-
- try {
- synchronized (this) {
- // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
- // its own permission.
- if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires permission "
- + android.Manifest.permission.SET_ACTIVITY_WATCHER);
- }
-
- if (start && (profilerInfo == null || profilerInfo.profileFd == null)) {
- throw new IllegalArgumentException("null profile info or fd");
- }
-
- ProcessRecord proc = null;
- if (process != null) {
- proc = findProcessLocked(process, userId, "profileControl");
- }
-
- if (start && (proc == null || proc.thread == null)) {
- throw new IllegalArgumentException("Unknown process: " + process);
- }
-
- if (start) {
- stopProfilerLocked(null, 0);
- setProfileApp(proc.info, proc.processName, profilerInfo);
- mProfileData.setProfileProc(proc);
- mProfileType = profileType;
- ParcelFileDescriptor fd = profilerInfo.profileFd;
- try {
- fd = fd.dup();
- } catch (IOException e) {
- fd = null;
- }
- profilerInfo.profileFd = fd;
- proc.thread.profilerControl(start, profilerInfo, profileType);
- fd = null;
- try {
- mProfileData.getProfilerInfo().profileFd.close();
- } catch (IOException e) {
- }
- mProfileData.getProfilerInfo().profileFd = null;
-
- if (proc.pid == MY_PID) {
- // When profiling the system server itself, avoid closing the file
- // descriptor, as profilerControl will not create a copy.
- // Note: it is also not correct to just set profileFd to null, as the
- // whole ProfilerInfo instance is passed down!
- profilerInfo = null;
- }
- } else {
- stopProfilerLocked(proc, profileType);
- if (profilerInfo != null && profilerInfo.profileFd != null) {
- try {
- profilerInfo.profileFd.close();
- } catch (IOException e) {
- }
- }
- }
-
- return true;
+ synchronized (this) {
+ // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
+ // its own permission.
+ if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
- } catch (RemoteException e) {
- throw new IllegalStateException("Process disappeared");
- } finally {
- if (profilerInfo != null && profilerInfo.profileFd != null) {
- try {
- profilerInfo.profileFd.close();
- } catch (IOException e) {
- }
+
+ if (start && (profilerInfo == null || profilerInfo.profileFd == null)) {
+ throw new IllegalArgumentException("null profile info or fd");
}
+
+ ProcessRecord proc = null;
+ if (process != null) {
+ proc = findProcessLocked(process, userId, "profileControl");
+ }
+
+ if (start && (proc == null || proc.thread == null)) {
+ throw new IllegalArgumentException("Unknown process: " + process);
+ }
+
+ return mAppProfiler.profileControlLocked(proc, start, profilerInfo, profileType);
}
}
@@ -16809,7 +15412,7 @@
throw new IllegalArgumentException("Unknown process: " + process);
}
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+ boolean isDebuggable = Build.IS_DEBUGGABLE;
if (!isDebuggable) {
if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
throw new SecurityException("Process not debuggable: " + proc);
@@ -16868,45 +15471,12 @@
}
}
}
- synchronized (this) {
- if (maxMemSize > 0) {
- mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage));
- } else {
- if (uid != 0) {
- mMemWatchProcesses.remove(processName, uid);
- } else {
- mMemWatchProcesses.getMap().remove(processName);
- }
- }
- }
+ mAppProfiler.setDumpHeapDebugLimit(processName, uid, maxMemSize, reportPackage);
}
@Override
public void dumpHeapFinished(String path) {
- synchronized (this) {
- if (Binder.getCallingPid() != mMemWatchDumpPid) {
- Slog.w(TAG, "dumpHeapFinished: Calling pid " + Binder.getCallingPid()
- + " does not match last pid " + mMemWatchDumpPid);
- return;
- }
- if (mMemWatchDumpUri == null || !mMemWatchDumpUri.getPath().equals(path)) {
- Slog.w(TAG, "dumpHeapFinished: Calling path " + path
- + " does not match last path " + mMemWatchDumpUri);
- return;
- }
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
- mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
-
- // Forced gc to clean up the remnant hprof fd.
- Runtime.getRuntime().gc();
- }
- }
-
- /** Clear the currently executing heap dump variables so a new heap dump can be started. */
- private void abortHeapDump(String procName) {
- Message msg = mHandler.obtainMessage(ABORT_DUMPHEAP_MSG);
- msg.obj = procName;
- mHandler.sendMessage(msg);
+ mAppProfiler.dumpHeapFinished(path, Binder.getCallingPid());
}
/** In this method we try to acquire our lock to make sure that we have not deadlocked */
@@ -17058,8 +15628,7 @@
return false;
}
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
+ if (!Build.IS_DEBUGGABLE) {
if ((process.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
return false;
}
@@ -17489,7 +16058,7 @@
@Override
public void updateCpuStats() {
synchronized (ActivityManagerService.this) {
- ActivityManagerService.this.updateCpuStats();
+ ActivityManagerService.this.updateCpuStatsLocked();
}
}
@@ -17513,19 +16082,7 @@
@Override
public void updateForegroundTimeIfOnBattery(
String packageName, int uid, long cpuTimeDiff) {
- synchronized (ActivityManagerService.this) {
- if (!mBatteryStatsService.isOnBattery()) {
- return;
- }
- final BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
- synchronized (bsi) {
- final BatteryStatsImpl.Uid.Proc ps =
- bsi.getProcessStatsLocked(uid, packageName);
- if (ps != null) {
- ps.addForegroundTimeLocked(cpuTimeDiff);
- }
- }
- }
+ mBatteryStatsService.updateForegroundTimeIfOnBattery(packageName, uid, cpuTimeDiff);
}
@Override
@@ -18420,8 +16977,7 @@
throw new IllegalArgumentException("Unknown process: " + process);
}
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
+ if (!Build.IS_DEBUGGABLE) {
if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
throw new SecurityException("Process not debuggable: " + proc);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index a512cca..9ce8b11 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -28,6 +28,7 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AppGlobals;
import android.app.BroadcastOptions;
import android.app.IActivityController;
@@ -2586,7 +2587,7 @@
case "list":
return runStackList(pw);
case "info":
- return runStackInfo(pw);
+ return runRootTaskInfo(pw);
case "move-top-activity-to-pinned-stack":
return runMoveTopActivityToPinnedStack(pw);
case "remove":
@@ -2668,17 +2669,17 @@
}
int runStackList(PrintWriter pw) throws RemoteException {
- List<ActivityManager.StackInfo> stacks = mTaskInterface.getAllStackInfos();
- for (ActivityManager.StackInfo info : stacks) {
+ List<RootTaskInfo> tasks = mTaskInterface.getAllRootTaskInfos();
+ for (RootTaskInfo info : tasks) {
pw.println(info);
}
return 0;
}
- int runStackInfo(PrintWriter pw) throws RemoteException {
+ int runRootTaskInfo(PrintWriter pw) throws RemoteException {
int windowingMode = Integer.parseInt(getNextArgRequired());
int activityType = Integer.parseInt(getNextArgRequired());
- ActivityManager.StackInfo info = mTaskInterface.getStackInfo(windowingMode, activityType);
+ RootTaskInfo info = mTaskInterface.getRootTaskInfo(windowingMode, activityType);
pw.println(info);
return 0;
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 5d429d3..3f55bff 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -22,7 +22,6 @@
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.MY_PID;
-import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -36,10 +35,10 @@
import android.content.pm.VersionedPackage;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArrayMap;
@@ -596,7 +595,7 @@
return mService.mAtmInternal.handleAppCrashInActivityController(
name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> {
- if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
+ if (Build.IS_DEBUGGABLE
&& "Native crash".equals(crashInfo.exceptionClassName)) {
Slog.w(TAG, "Skip killing native crashed app " + name
+ "(" + pid + ") during testing");
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
new file mode 100644
index 0000000..0b5d585
--- /dev/null
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -0,0 +1,1731 @@
+/*
+ * Copyright (C) 2020 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.server.am;
+
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
+import static android.os.Process.FIRST_APPLICATION_UID;
+
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS;
+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.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+
+import android.annotation.BroadcastBehavior;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.app.IApplicationThread;
+import android.app.ProfilerInfo;
+import android.content.ComponentCallbacks2;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.DebugUtils;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.ProcessMap;
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.MemInfoReader;
+import com.android.server.am.ProcessList.ProcStateMemTracker;
+import com.android.server.utils.PriorityDump;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * A helper class taking care of the profiling, memory and cpu sampling of apps
+ */
+public class AppProfiler {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
+
+ static final String TAG_PSS = TAG + POSTFIX_PSS;
+
+ static final String TAG_OOM_ADJ = ActivityManagerService.TAG_OOM_ADJ;
+
+ /** Control over CPU and battery monitoring */
+ // write battery stats every 30 minutes.
+ static final long BATTERY_STATS_TIME = 30 * 60 * 1000;
+
+ static final boolean MONITOR_CPU_USAGE = true;
+
+ // don't sample cpu less than every 5 seconds.
+ static final long MONITOR_CPU_MIN_TIME = 5 * 1000;
+
+ // wait possibly forever for next cpu sample.
+ static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;
+
+ static final boolean MONITOR_THREAD_CPU_USAGE = false;
+
+ static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer";
+
+ /**
+ * Broadcast sent when heap dump collection has been completed.
+ */
+ @BroadcastBehavior(includeBackground = true, protectedBroadcast = true)
+ private static final String ACTION_HEAP_DUMP_FINISHED =
+ "com.android.internal.intent.action.HEAP_DUMP_FINISHED";
+
+ /**
+ * The process we are reporting
+ */
+ private static final String EXTRA_HEAP_DUMP_PROCESS_NAME =
+ "com.android.internal.extra.heap_dump.PROCESS_NAME";
+
+ /**
+ * The size limit the process reached.
+ */
+ private static final String EXTRA_HEAP_DUMP_SIZE_BYTES =
+ "com.android.internal.extra.heap_dump.SIZE_BYTES";
+
+ /**
+ * Whether the user initiated the dump or not.
+ */
+ private static final String EXTRA_HEAP_DUMP_IS_USER_INITIATED =
+ "com.android.internal.extra.heap_dump.IS_USER_INITIATED";
+
+ /**
+ * Optional name of package to directly launch.
+ */
+ private static final String EXTRA_HEAP_DUMP_REPORT_PACKAGE =
+ "com.android.internal.extra.heap_dump.REPORT_PACKAGE";
+
+ /**
+ * How long we defer PSS gathering while activities are starting, in milliseconds.
+ * This is adjustable via DeviceConfig. If it is zero or negative, no PSS deferral
+ * is done.
+ */
+ private volatile long mPssDeferralTime = 0;
+
+ /**
+ * Processes we want to collect PSS data from.
+ */
+ @GuardedBy("mService")
+ private final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
+
+ /**
+ * Depth of overlapping activity-start PSS deferral notes
+ */
+ private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0);
+
+ /**
+ * Last time we requested PSS data of all processes.
+ */
+ @GuardedBy("mService")
+ private long mLastFullPssTime = SystemClock.uptimeMillis();
+
+ /**
+ * If set, the next time we collect PSS data we should do a full collection
+ * with data from native processes and the kernel.
+ */
+ @GuardedBy("mService")
+ private boolean mFullPssPending = false;
+
+ /**
+ * If true, we are running under a test environment so will sample PSS from processes
+ * much more rapidly to try to collect better data when the tests are rapidly
+ * running through apps.
+ */
+ @GuardedBy("mService")
+ private boolean mTestPssMode = false;
+
+ @GuardedBy("mService")
+ private final LowMemDetector mLowMemDetector;
+
+ /**
+ * Allow the current computed overall memory level of the system to go down?
+ * This is set to false when we are killing processes for reasons other than
+ * memory management, so that the now smaller process list will not be taken as
+ * an indication that memory is tighter.
+ */
+ @GuardedBy("mService")
+ private boolean mAllowLowerMemLevel = false;
+
+ /**
+ * The last computed memory level, for holding when we are in a state that
+ * processes are going away for other reasons.
+ */
+ @GuardedBy("mService")
+ private int mLastMemoryLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+
+ /**
+ * The last total number of process we have, to determine if changes actually look
+ * like a shrinking number of process due to lower RAM.
+ */
+ @GuardedBy("mService")
+ private int mLastNumProcesses;
+
+ /**
+ * Total time spent with RAM that has been added in the past since the last idle time.
+ */
+ @GuardedBy("mService")
+ private long mLowRamTimeSinceLastIdle = 0;
+
+ /**
+ * If RAM is currently low, when that horrible situation started.
+ */
+ @GuardedBy("mService")
+ private long mLowRamStartTime = 0;
+
+ /**
+ * Stores a map of process name -> agent string. When a process is started and mAgentAppMap
+ * is not null, this map is checked and the mapped agent installed during bind-time. Note:
+ * A non-null agent in mProfileInfo overrides this.
+ */
+ private @Nullable Map<String, String> mAppAgentMap = null;
+
+ private int mProfileType = 0;
+ private final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
+ private String mMemWatchDumpProcName;
+ private Uri mMemWatchDumpUri;
+ private int mMemWatchDumpPid;
+ private int mMemWatchDumpUid;
+ private boolean mMemWatchIsUserInitiated;
+
+ /**
+ * Used to collect per-process CPU use for ANRs, battery stats, etc.
+ * Must acquire this object's lock when accessing it.
+ * NOTE: this lock will be held while doing long operations (trawling
+ * through all processes in /proc), so it should never be acquired by
+ * any critical paths such as when holding the main activity manager lock.
+ */
+ private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(
+ MONITOR_THREAD_CPU_USAGE);
+ private final AtomicLong mLastCpuTime = new AtomicLong(0);
+ private final AtomicBoolean mProcessCpuMutexFree = new AtomicBoolean(true);
+ private final CountDownLatch mProcessCpuInitLatch = new CountDownLatch(1);
+
+ private long mLastWriteTime = 0;
+ private final ProfileData mProfileData = new ProfileData();
+
+ /**
+ * Runtime CPU use collection thread. This object's lock is used to
+ * perform synchronization with the thread (notifying it to run).
+ */
+ private final Thread mProcessCpuThread;
+
+ private final ActivityManagerService mService;
+ private final Handler mBgHandler;
+
+ /**
+ * Observe DeviceConfig changes to the PSS calculation interval
+ */
+ private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener =
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(Properties properties) {
+ if (properties.getKeyset().contains(ACTIVITY_START_PSS_DEFER_CONFIG)) {
+ mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Activity-start PSS delay now "
+ + mPssDeferralTime + " ms");
+ }
+ }
+ }
+ };
+
+ private class ProfileData {
+ private String mProfileApp = null;
+ private ProcessRecord mProfileProc = null;
+ private ProfilerInfo mProfilerInfo = null;
+
+ void setProfileApp(String profileApp) {
+ mProfileApp = profileApp;
+ if (mService.mAtmInternal != null) {
+ mService.mAtmInternal.setProfileApp(profileApp);
+ }
+ }
+
+ String getProfileApp() {
+ return mProfileApp;
+ }
+
+ void setProfileProc(ProcessRecord profileProc) {
+ mProfileProc = profileProc;
+ if (mService.mAtmInternal != null) {
+ mService.mAtmInternal.setProfileProc(profileProc == null ? null
+ : profileProc.getWindowProcessController());
+ }
+ }
+
+ ProcessRecord getProfileProc() {
+ return mProfileProc;
+ }
+
+ void setProfilerInfo(ProfilerInfo profilerInfo) {
+ mProfilerInfo = profilerInfo;
+ if (mService.mAtmInternal != null) {
+ mService.mAtmInternal.setProfilerInfo(profilerInfo);
+ }
+ }
+
+ ProfilerInfo getProfilerInfo() {
+ return mProfilerInfo;
+ }
+ }
+
+ private class BgHandler extends Handler {
+ static final int COLLECT_PSS_BG_MSG = 1;
+ static final int DEFER_PSS_MSG = 2;
+ static final int STOP_DEFERRING_PSS_MSG = 3;
+ BgHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case COLLECT_PSS_BG_MSG:
+ collectPssInBackground();
+ break;
+ case DEFER_PSS_MSG:
+ deferPssForActivityStart();
+ break;
+ case STOP_DEFERRING_PSS_MSG:
+ stopDeferPss();
+ break;
+ }
+ }
+ }
+
+ private void collectPssInBackground() {
+ long start = SystemClock.uptimeMillis();
+ MemInfoReader memInfo = null;
+ synchronized (mService) {
+ if (mFullPssPending) {
+ mFullPssPending = false;
+ memInfo = new MemInfoReader();
+ }
+ }
+ if (memInfo != null) {
+ updateCpuStatsNow();
+ long nativeTotalPss = 0;
+ final List<ProcessCpuTracker.Stats> stats;
+ synchronized (mProcessCpuTracker) {
+ stats = mProcessCpuTracker.getStats(st -> {
+ return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
+ });
+ }
+ final int numOfStats = stats.size();
+ for (int j = 0; j < numOfStats; j++) {
+ synchronized (mService.mPidsSelfLocked) {
+ if (mService.mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) {
+ // This is one of our own processes; skip it.
+ continue;
+ }
+ }
+ nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null);
+ }
+ memInfo.readMemInfo();
+ synchronized (mService.mProcessStats.mLock) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Collected native and kernel memory in "
+ + (SystemClock.uptimeMillis() - start) + "ms");
+ }
+ final long cachedKb = memInfo.getCachedSizeKb();
+ final long freeKb = memInfo.getFreeSizeKb();
+ final long zramKb = memInfo.getZramTotalSizeKb();
+ final long kernelKb = memInfo.getKernelUsedSizeKb();
+ EventLogTags.writeAmMeminfo(cachedKb * 1024, freeKb * 1024, zramKb * 1024,
+ kernelKb * 1024, nativeTotalPss * 1024);
+ mService.mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
+ nativeTotalPss);
+ }
+ }
+
+ int num = 0;
+ long[] tmp = new long[3];
+ do {
+ ProcessRecord proc;
+ int procState;
+ int statType;
+ int pid = -1;
+ long lastPssTime;
+ synchronized (mService) {
+ if (mPendingPssProcesses.size() <= 0) {
+ if (mTestPssMode || DEBUG_PSS) {
+ Slog.d(TAG_PSS,
+ "Collected pss of " + num + " processes in "
+ + (SystemClock.uptimeMillis() - start) + "ms");
+ }
+ mPendingPssProcesses.clear();
+ return;
+ }
+ proc = mPendingPssProcesses.remove(0);
+ procState = proc.pssProcState;
+ statType = proc.pssStatType;
+ lastPssTime = proc.lastPssTime;
+ long now = SystemClock.uptimeMillis();
+ if (proc.thread != null && procState == proc.setProcState
+ && (lastPssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) < now) {
+ pid = proc.pid;
+ } else {
+ abortNextPssTime(proc.procStateMemTracker);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Skipped pss collection of " + pid
+ + ": still need "
+ + (lastPssTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE - now)
+ + "ms until safe");
+ }
+ proc = null;
+ pid = 0;
+ }
+ }
+ if (proc != null) {
+ long startTime = SystemClock.currentThreadTimeMillis();
+ // skip background PSS calculation of apps that are capturing
+ // camera imagery
+ final boolean usingCamera = mService.isCameraActiveForUid(proc.uid);
+ long pss = usingCamera ? 0 : Debug.getPss(pid, tmp, null);
+ long endTime = SystemClock.currentThreadTimeMillis();
+ synchronized (mService) {
+ if (pss != 0 && proc.thread != null && proc.setProcState == procState
+ && proc.pid == pid && proc.lastPssTime == lastPssTime) {
+ num++;
+ commitNextPssTime(proc.procStateMemTracker);
+ recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1], tmp[2],
+ statType, endTime - startTime, SystemClock.uptimeMillis());
+ } else {
+ abortNextPssTime(proc.procStateMemTracker);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Skipped pss collection of " + pid
+ + ": " + (proc.thread == null ? "NO_THREAD " : "")
+ + (usingCamera ? "CAMERA " : "")
+ + (proc.pid != pid ? "PID_CHANGED " : "")
+ + " initState=" + procState + " curState="
+ + proc.setProcState + " "
+ + (proc.lastPssTime != lastPssTime ? "TIME_CHANGED" : ""));
+ }
+ }
+ }
+ }
+ } while (true);
+ }
+
+ private static void commitNextPssTime(ProcStateMemTracker tracker) {
+ if (tracker.mPendingMemState >= 0) {
+ tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
+ tracker.mScalingFactor[tracker.mPendingMemState] = tracker.mPendingScalingFactor;
+ tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
+ tracker.mPendingMemState = -1;
+ }
+ }
+
+ private static void abortNextPssTime(ProcStateMemTracker tracker) {
+ tracker.mPendingMemState = -1;
+ }
+
+ @GuardedBy("mService")
+ void updateNextPssTimeLocked(int procState, ProcessRecord app, long now, boolean forceUpdate) {
+ if (!forceUpdate) {
+ if (now <= app.nextPssTime
+ && now <= Math.max(app.lastPssTime + ProcessList.PSS_MAX_INTERVAL,
+ app.lastStateTime + ProcessList.minTimeFromStateChange(mTestPssMode))) {
+ // update is not due, ignore it.
+ return;
+ }
+ if (!requestPssLocked(app, app.setProcState)) {
+ return;
+ }
+ }
+ app.nextPssTime = ProcessList.computeNextPssTime(procState, app.procStateMemTracker,
+ mTestPssMode, mService.mAtmInternal.isSleeping(), now);
+ }
+
+ /**
+ * Record new PSS sample for a process.
+ */
+ @GuardedBy("mService")
+ private void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss,
+ long swapPss, long rss, int statType, long pssDuration, long now) {
+ EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
+ swapPss * 1024, rss * 1024, statType, procState, pssDuration);
+ proc.lastPssTime = now;
+ synchronized (mService.mProcessStats.mLock) {
+ proc.baseProcessTracker.addPss(
+ pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
+ }
+ for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) {
+ ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
+ proc.info.uid,
+ holder.state.getName(),
+ holder.state.getPackage(),
+ pss, uss, rss, statType, pssDuration,
+ holder.appVersion);
+ }
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS,
+ "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+ + " state=" + ProcessList.makeProcStateString(procState));
+ }
+ if (proc.initialIdlePss == 0) {
+ proc.initialIdlePss = pss;
+ }
+ proc.lastPss = pss;
+ proc.lastSwapPss = swapPss;
+ if (procState >= ActivityManager.PROCESS_STATE_HOME) {
+ proc.lastCachedPss = pss;
+ proc.lastCachedSwapPss = swapPss;
+ }
+ proc.mLastRss = rss;
+
+ final SparseArray<Pair<Long, String>> watchUids =
+ mMemWatchProcesses.getMap().get(proc.processName);
+ Long check = null;
+ if (watchUids != null) {
+ Pair<Long, String> val = watchUids.get(proc.uid);
+ if (val == null) {
+ val = watchUids.get(0);
+ }
+ if (val != null) {
+ check = val.first;
+ }
+ }
+ if (check != null) {
+ if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
+ boolean isDebuggable = Build.IS_DEBUGGABLE;
+ if (!isDebuggable) {
+ if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ isDebuggable = true;
+ }
+ }
+ if (isDebuggable) {
+ Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting");
+ startHeapDumpLocked(proc, false);
+ } else {
+ Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check
+ + ", but debugging not enabled");
+ }
+ }
+ }
+ }
+
+ private final class RecordPssRunnable implements Runnable {
+ private final ProcessRecord mProc;
+ private final Uri mDumpUri;
+ private final ContentResolver mContentResolver;
+
+ RecordPssRunnable(ProcessRecord proc, Uri dumpUri, ContentResolver contentResolver) {
+ mProc = proc;
+ mDumpUri = dumpUri;
+ mContentResolver = contentResolver;
+ }
+
+ @Override
+ public void run() {
+ try (ParcelFileDescriptor fd = mContentResolver.openFileDescriptor(mDumpUri, "rw")) {
+ IApplicationThread thread = mProc.thread;
+ if (thread != null) {
+ try {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Requesting dump heap from "
+ + mProc + " to " + mDumpUri.getPath());
+ }
+ thread.dumpHeap(/* managed= */ true,
+ /* mallocInfo= */ false, /* runGc= */ false,
+ mDumpUri.getPath(), fd,
+ /* finishCallback= */ null);
+ } catch (RemoteException e) {
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to dump heap", e);
+ // Need to clear the heap dump variables, otherwise no further heap dumps will be
+ // attempted.
+ abortHeapDump(mProc.processName);
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void startHeapDumpLocked(ProcessRecord proc, boolean isUserInitiated) {
+ mMemWatchDumpProcName = proc.processName;
+ mMemWatchDumpUri = makeHeapDumpUri(proc.processName);
+ mMemWatchDumpPid = proc.pid;
+ mMemWatchDumpUid = proc.uid;
+ mMemWatchIsUserInitiated = isUserInitiated;
+ Context ctx;
+ try {
+ ctx = mService.mContext.createPackageContextAsUser("android", 0,
+ UserHandle.getUserHandleForUid(mMemWatchDumpUid));
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("android package not found.");
+ }
+ BackgroundThread.getHandler().post(
+ new RecordPssRunnable(proc, mMemWatchDumpUri, ctx.getContentResolver()));
+ }
+
+ void dumpHeapFinished(String path, int callerPid) {
+ synchronized (mService) {
+ if (callerPid != mMemWatchDumpPid) {
+ Slog.w(TAG, "dumpHeapFinished: Calling pid " + Binder.getCallingPid()
+ + " does not match last pid " + mMemWatchDumpPid);
+ return;
+ }
+ if (mMemWatchDumpUri == null || !mMemWatchDumpUri.getPath().equals(path)) {
+ Slog.w(TAG, "dumpHeapFinished: Calling path " + path
+ + " does not match last path " + mMemWatchDumpUri);
+ return;
+ }
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
+ mService.mHandler.sendEmptyMessage(
+ ActivityManagerService.POST_DUMP_HEAP_NOTIFICATION_MSG);
+
+ // Forced gc to clean up the remnant hprof fd.
+ Runtime.getRuntime().gc();
+ }
+ }
+
+ void handlePostDumpHeapNotification() {
+ final String procName;
+ final int uid;
+ final long memLimit;
+ final String reportPackage;
+ final boolean isUserInitiated;
+ synchronized (mService) {
+ uid = mMemWatchDumpUid;
+ procName = mMemWatchDumpProcName;
+ Pair<Long, String> val = mMemWatchProcesses.get(procName, uid);
+ if (val == null) {
+ val = mMemWatchProcesses.get(procName, 0);
+ }
+ if (val != null) {
+ memLimit = val.first;
+ reportPackage = val.second;
+ } else {
+ memLimit = 0;
+ reportPackage = null;
+ }
+ isUserInitiated = mMemWatchIsUserInitiated;
+
+ mMemWatchDumpUri = null;
+ mMemWatchDumpProcName = null;
+ mMemWatchDumpPid = -1;
+ mMemWatchDumpUid = -1;
+ }
+ if (procName == null) {
+ return;
+ }
+
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Showing dump heap notification from " + procName + "/" + uid);
+ }
+
+ Intent dumpFinishedIntent = new Intent(ACTION_HEAP_DUMP_FINISHED);
+ // Send this only to the Shell package.
+ dumpFinishedIntent.setPackage("com.android.shell");
+ dumpFinishedIntent.putExtra(Intent.EXTRA_UID, uid);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_IS_USER_INITIATED, isUserInitiated);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_SIZE_BYTES, memLimit);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_REPORT_PACKAGE, reportPackage);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_PROCESS_NAME, procName);
+
+ mService.mContext.sendBroadcastAsUser(dumpFinishedIntent,
+ UserHandle.getUserHandleForUid(uid));
+ }
+
+ void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
+ String reportPackage) {
+ synchronized (mService) {
+ if (maxMemSize > 0) {
+ mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage));
+ } else {
+ if (uid != 0) {
+ mMemWatchProcesses.remove(processName, uid);
+ } else {
+ mMemWatchProcesses.getMap().remove(processName);
+ }
+ }
+ }
+ }
+
+ /** Clear the currently executing heap dump variables so a new heap dump can be started. */
+ private void abortHeapDump(String procName) {
+ Message msg = mService.mHandler.obtainMessage(ActivityManagerService.ABORT_DUMPHEAP_MSG);
+ msg.obj = procName;
+ mService.mHandler.sendMessage(msg);
+ }
+
+ void handleAbortDumpHeap(String procName) {
+ if (procName != null) {
+ synchronized (mService) {
+ if (procName.equals(mMemWatchDumpProcName)) {
+ mMemWatchDumpProcName = null;
+ mMemWatchDumpUri = null;
+ mMemWatchDumpPid = -1;
+ mMemWatchDumpUid = -1;
+ }
+ }
+ }
+ }
+
+ /** @hide */
+ private static Uri makeHeapDumpUri(String procName) {
+ return Uri.parse("content://com.android.shell.heapdump/" + procName + "_javaheap.bin");
+ }
+
+ /**
+ * Schedule PSS collection of a process.
+ */
+ @GuardedBy("mService")
+ private boolean requestPssLocked(ProcessRecord proc, int procState) {
+ if (mPendingPssProcesses.contains(proc)) {
+ return false;
+ }
+ if (mPendingPssProcesses.size() == 0) {
+ final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0)
+ ? mPssDeferralTime : 0;
+ if (DEBUG_PSS && deferral > 0) {
+ Slog.d(TAG_PSS, "requestPssLocked() deferring PSS request by "
+ + deferral + " ms");
+ }
+ mBgHandler.sendEmptyMessageDelayed(BgHandler.COLLECT_PSS_BG_MSG, deferral);
+ }
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
+ proc.pssProcState = procState;
+ proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE;
+ mPendingPssProcesses.add(proc);
+ return true;
+ }
+
+ /**
+ * Re-defer a posted PSS collection pass, if one exists. Assumes deferral is
+ * currently active policy when called.
+ */
+ @GuardedBy("mService")
+ private void deferPssIfNeededLocked() {
+ if (mPendingPssProcesses.size() > 0) {
+ mBgHandler.removeMessages(BgHandler.COLLECT_PSS_BG_MSG);
+ mBgHandler.sendEmptyMessageDelayed(BgHandler.COLLECT_PSS_BG_MSG, mPssDeferralTime);
+ }
+ }
+
+ private void deferPssForActivityStart() {
+ if (mPssDeferralTime > 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Deferring PSS collection for activity start");
+ }
+ deferPssIfNeededLocked();
+ mActivityStartingNesting.getAndIncrement();
+ mBgHandler.sendEmptyMessageDelayed(BgHandler.STOP_DEFERRING_PSS_MSG, mPssDeferralTime);
+ }
+ }
+
+ private void stopDeferPss() {
+ final int nesting = mActivityStartingNesting.decrementAndGet();
+ if (nesting <= 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now "
+ + nesting);
+ }
+ if (nesting < 0) {
+ Slog.wtf(TAG, "Activity start nesting undercount!");
+ mActivityStartingNesting.incrementAndGet();
+ }
+ } else {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting);
+ }
+ }
+ }
+
+ /**
+ * Schedule PSS collection of all processes.
+ */
+ @GuardedBy("mService")
+ void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
+ if (!always) {
+ if (now < (mLastFullPssTime
+ + (memLowered ? mService.mConstants.FULL_PSS_LOWERED_INTERVAL
+ : mService.mConstants.FULL_PSS_MIN_INTERVAL))) {
+ return;
+ }
+ }
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Requesting pss of all procs! memLowered=" + memLowered);
+ }
+ mLastFullPssTime = now;
+ mFullPssPending = true;
+ for (int i = mPendingPssProcesses.size() - 1; i >= 0; i--) {
+ abortNextPssTime(mPendingPssProcesses.get(i).procStateMemTracker);
+ }
+ mPendingPssProcesses.ensureCapacity(mService.mProcessList.getLruSizeLocked());
+ mPendingPssProcesses.clear();
+ for (int i = mService.mProcessList.getLruSizeLocked() - 1; i >= 0; i--) {
+ ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ if (app.thread == null || app.getCurProcState() == PROCESS_STATE_NONEXISTENT) {
+ continue;
+ }
+ if (memLowered || (always && now
+ > app.lastStateTime + ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
+ || now > (app.lastStateTime + ProcessList.PSS_ALL_INTERVAL)) {
+ app.pssProcState = app.setProcState;
+ app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
+ : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
+ updateNextPssTimeLocked(app.getCurProcState(), app, now, true);
+ mPendingPssProcesses.add(app);
+ }
+ }
+ if (!mBgHandler.hasMessages(BgHandler.COLLECT_PSS_BG_MSG)) {
+ mBgHandler.sendEmptyMessage(BgHandler.COLLECT_PSS_BG_MSG);
+ }
+ }
+
+ void setTestPssMode(boolean enabled) {
+ synchronized (mService) {
+ mTestPssMode = enabled;
+ if (enabled) {
+ // Whenever we enable the mode, we want to take a snapshot all of current
+ // process mem use.
+ requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, true);
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ boolean getTestPssModeLocked() {
+ return mTestPssMode;
+ }
+
+ @GuardedBy("mService")
+ int getLastMemoryLevelLocked() {
+ return mLastMemoryLevel;
+ }
+
+ @GuardedBy("mService")
+ boolean isLastMemoryLevelNormal() {
+ return mLastMemoryLevel <= ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+
+ @GuardedBy("mService")
+ void updateLowRamTimestampLocked(long now) {
+ mLowRamTimeSinceLastIdle = 0;
+ if (mLowRamStartTime != 0) {
+ mLowRamStartTime = now;
+ }
+ }
+
+ @GuardedBy("mService")
+ void setAllowLowerMemLevelLocked(boolean allowLowerMemLevel) {
+ mAllowLowerMemLevel = allowLowerMemLevel;
+ }
+
+ @GuardedBy("mService")
+ boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
+ final int numOfLru = mService.mProcessList.getLruSizeLocked();
+ final long now = SystemClock.uptimeMillis();
+ int memFactor;
+ if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
+ memFactor = mLowMemDetector.getMemFactor();
+ } else {
+ // Now determine the memory trimming level of background processes.
+ // Unfortunately we need to start at the back of the list to do this
+ // properly. We only do this if the number of background apps we
+ // are managing to keep around is less than half the maximum we desire;
+ // if we are keeping a good number around, we'll let them use whatever
+ // memory they want.
+ if (numCached <= mService.mConstants.CUR_TRIM_CACHED_PROCESSES
+ && numEmpty <= mService.mConstants.CUR_TRIM_EMPTY_PROCESSES) {
+ final int numCachedAndEmpty = numCached + numEmpty;
+ if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
+ } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
+ } else {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+ }
+ } else {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+ }
+ // We always allow the memory level to go up (better). We only allow it to go
+ // down if we are in a state where that is allowed, *and* the total number of processes
+ // has gone down since last time.
+ if (DEBUG_OOM_ADJ) {
+ Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+ + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
+ + " numProcs=" + mService.mProcessList.getLruSizeLocked()
+ + " last=" + mLastNumProcesses);
+ }
+ if (memFactor > mLastMemoryLevel) {
+ if (!mAllowLowerMemLevel
+ || mService.mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
+ memFactor = mLastMemoryLevel;
+ if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
+ }
+ }
+ if (memFactor != mLastMemoryLevel) {
+ EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
+ FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
+ }
+ mLastMemoryLevel = memFactor;
+ mLastNumProcesses = mService.mProcessList.getLruSizeLocked();
+ boolean allChanged;
+ int trackerMemFactor;
+ synchronized (mService.mProcessStats.mLock) {
+ allChanged = mService.mProcessStats.setMemFactorLocked(memFactor,
+ mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(), now);
+ trackerMemFactor = mService.mProcessStats.getMemFactorLocked();
+ }
+ if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
+ if (mLowRamStartTime == 0) {
+ mLowRamStartTime = now;
+ }
+ int step = 0;
+ int fgTrimLevel;
+ switch (memFactor) {
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+ break;
+ default:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+ break;
+ }
+ int factor = numTrimming / 3;
+ int minFactor = 2;
+ if (mService.mAtmInternal.getHomeProcess() != null) minFactor++;
+ if (mService.mAtmInternal.getPreviousProcess() != null) minFactor++;
+ if (factor < minFactor) factor = minFactor;
+ int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
+ for (int i = numOfLru - 1; i >= 0; i--) {
+ ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ if (allChanged || app.procStateChanged) {
+ mService.setProcessTrackerStateLocked(app, trackerMemFactor, now);
+ app.procStateChanged = false;
+ }
+ if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
+ && !app.killedByAm) {
+ if (app.trimMemoryLevel < curLevel && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+ Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of " + app.processName
+ + " to " + curLevel);
+ }
+ app.thread.scheduleTrimMemory(curLevel);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = curLevel;
+ step++;
+ if (step >= factor) {
+ step = 0;
+ switch (curLevel) {
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+ break;
+ }
+ }
+ } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+ && !app.killedByAm) {
+ if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
+ && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+ Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of heavy-weight " + app.processName
+ + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+ }
+ app.thread.scheduleTrimMemory(
+ ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+ } else {
+ if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || app.systemNoUi) && app.hasPendingUiClean()) {
+ // If this application is now in the background and it
+ // had done UI, then give it the special trim level to
+ // have it free UI resources.
+ final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+ if (app.trimMemoryLevel < level && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+ Slog.v(TAG_OOM_ADJ, "Trimming memory of bg-ui "
+ + app.processName + " to " + level);
+ }
+ app.thread.scheduleTrimMemory(level);
+ } catch (RemoteException e) {
+ }
+ }
+ app.setPendingUiClean(false);
+ }
+ if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+ Slog.v(TAG_OOM_ADJ, "Trimming memory of fg " + app.processName
+ + " to " + fgTrimLevel);
+ }
+ app.thread.scheduleTrimMemory(fgTrimLevel);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = fgTrimLevel;
+ }
+ }
+ } else {
+ if (mLowRamStartTime != 0) {
+ mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
+ mLowRamStartTime = 0;
+ }
+ for (int i = numOfLru - 1; i >= 0; i--) {
+ ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ if (allChanged || app.procStateChanged) {
+ mService.setProcessTrackerStateLocked(app, trackerMemFactor, now);
+ app.procStateChanged = false;
+ }
+ if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || app.systemNoUi) && app.hasPendingUiClean()) {
+ if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
+ && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+ Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of ui hidden " + app.processName
+ + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ }
+ app.thread.scheduleTrimMemory(
+ ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ } catch (RemoteException e) {
+ }
+ }
+ app.setPendingUiClean(false);
+ }
+ app.trimMemoryLevel = 0;
+ }
+ }
+ return allChanged;
+ }
+
+ @GuardedBy("mService")
+ long getLowRamTimeSinceIdleLocked(long now) {
+ return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now - mLowRamStartTime) : 0);
+ }
+
+ @GuardedBy("mService")
+ private void stopProfilerLocked(ProcessRecord proc, int profileType) {
+ if (proc == null || proc == mProfileData.getProfileProc()) {
+ proc = mProfileData.getProfileProc();
+ profileType = mProfileType;
+ clearProfilerLocked();
+ }
+ if (proc == null) {
+ return;
+ }
+ try {
+ proc.thread.profilerControl(false, null, profileType);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Process disappeared");
+ }
+ }
+
+ @GuardedBy("mService")
+ void clearProfilerLocked() {
+ if (mProfileData.getProfilerInfo() != null
+ && mProfileData.getProfilerInfo().profileFd != null) {
+ try {
+ mProfileData.getProfilerInfo().profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ mProfileData.setProfileApp(null);
+ mProfileData.setProfileProc(null);
+ mProfileData.setProfilerInfo(null);
+ }
+
+ @GuardedBy("mService")
+ void clearProfilerLocked(ProcessRecord app) {
+ if (mProfileData.getProfileProc() == null
+ || mProfileData.getProfilerInfo() == null
+ || mProfileData.getProfileProc() != app) {
+ return;
+ }
+ clearProfilerLocked();
+ }
+
+ @GuardedBy("mService")
+ boolean profileControlLocked(ProcessRecord proc, boolean start,
+ ProfilerInfo profilerInfo, int profileType) {
+ try {
+ if (start) {
+ stopProfilerLocked(null, 0);
+ mService.setProfileApp(proc.info, proc.processName, profilerInfo);
+ mProfileData.setProfileProc(proc);
+ mProfileType = profileType;
+ ParcelFileDescriptor fd = profilerInfo.profileFd;
+ try {
+ fd = fd.dup();
+ } catch (IOException e) {
+ fd = null;
+ }
+ profilerInfo.profileFd = fd;
+ proc.thread.profilerControl(start, profilerInfo, profileType);
+ fd = null;
+ try {
+ mProfileData.getProfilerInfo().profileFd.close();
+ } catch (IOException e) {
+ }
+ mProfileData.getProfilerInfo().profileFd = null;
+
+ if (proc.pid == mService.MY_PID) {
+ // When profiling the system server itself, avoid closing the file
+ // descriptor, as profilerControl will not create a copy.
+ // Note: it is also not correct to just set profileFd to null, as the
+ // whole ProfilerInfo instance is passed down!
+ profilerInfo = null;
+ }
+ } else {
+ stopProfilerLocked(proc, profileType);
+ if (profilerInfo != null && profilerInfo.profileFd != null) {
+ try {
+ profilerInfo.profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ return true;
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Process disappeared");
+ } finally {
+ if (profilerInfo != null && profilerInfo.profileFd != null) {
+ try {
+ profilerInfo.profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void setProfileAppLocked(String processName, ProfilerInfo profilerInfo) {
+ mProfileData.setProfileApp(processName);
+
+ if (mProfileData.getProfilerInfo() != null) {
+ if (mProfileData.getProfilerInfo().profileFd != null) {
+ try {
+ mProfileData.getProfilerInfo().profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
+ mProfileType = 0;
+ }
+
+ @GuardedBy("mService")
+ void setProfileProcLocked(ProcessRecord proc) {
+ mProfileData.setProfileProc(proc);
+ }
+
+ @GuardedBy("mService")
+ void setAgentAppLocked(@NonNull String packageName, @Nullable String agent) {
+ if (agent == null) {
+ if (mAppAgentMap != null) {
+ mAppAgentMap.remove(packageName);
+ if (mAppAgentMap.isEmpty()) {
+ mAppAgentMap = null;
+ }
+ }
+ } else {
+ if (mAppAgentMap == null) {
+ mAppAgentMap = new HashMap<>();
+ }
+ if (mAppAgentMap.size() >= 100) {
+ // Limit the size of the map, to avoid OOMEs.
+ Slog.e(TAG, "App agent map has too many entries, cannot add " + packageName
+ + "/" + agent);
+ return;
+ }
+ mAppAgentMap.put(packageName, agent);
+ }
+ }
+
+ @GuardedBy("mService")
+ void updateCpuStatsLocked() {
+ final long now = SystemClock.uptimeMillis();
+ if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
+ return;
+ }
+ if (mProcessCpuMutexFree.compareAndSet(true, false)) {
+ synchronized (mProcessCpuThread) {
+ mProcessCpuThread.notify();
+ }
+ }
+ }
+
+ void updateCpuStatsNow() {
+ synchronized (mProcessCpuTracker) {
+ mProcessCpuMutexFree.set(false);
+ final long now = SystemClock.uptimeMillis();
+ boolean haveNewCpuStats = false;
+
+ if (MONITOR_CPU_USAGE
+ && mLastCpuTime.get() < (now - MONITOR_CPU_MIN_TIME)) {
+ mLastCpuTime.set(now);
+ mProcessCpuTracker.update();
+ if (mProcessCpuTracker.hasGoodLastStats()) {
+ haveNewCpuStats = true;
+ //Slog.i(TAG, mProcessCpu.printCurrentState());
+ //Slog.i(TAG, "Total CPU usage: "
+ // + mProcessCpu.getTotalCpuPercent() + "%");
+
+ // Slog the cpu usage if the property is set.
+ if ("true".equals(SystemProperties.get("events.cpu"))) {
+ int user = mProcessCpuTracker.getLastUserTime();
+ int system = mProcessCpuTracker.getLastSystemTime();
+ int iowait = mProcessCpuTracker.getLastIoWaitTime();
+ int irq = mProcessCpuTracker.getLastIrqTime();
+ int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
+ int idle = mProcessCpuTracker.getLastIdleTime();
+
+ int total = user + system + iowait + irq + softIrq + idle;
+ if (total == 0) total = 1;
+
+ EventLogTags.writeCpu(
+ ((user + system + iowait + irq + softIrq) * 100) / total,
+ (user * 100) / total,
+ (system * 100) / total,
+ (iowait * 100) / total,
+ (irq * 100) / total,
+ (softIrq * 100) / total);
+ }
+ }
+ }
+
+ final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics();
+ synchronized (bstats) {
+ if (haveNewCpuStats) {
+ if (bstats.startAddingCpuLocked()) {
+ int totalUTime = 0;
+ int totalSTime = 0;
+ final int statsCount = mProcessCpuTracker.countStats();
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ synchronized (mService.mPidsSelfLocked) {
+ for (int i = 0; i < statsCount; i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ if (!st.working) {
+ continue;
+ }
+ ProcessRecord pr = mService.mPidsSelfLocked.get(st.pid);
+ totalUTime += st.rel_utime;
+ totalSTime += st.rel_stime;
+ if (pr != null) {
+ BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
+ if (ps == null || !ps.isActive()) {
+ pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
+ pr.info.uid, pr.processName,
+ elapsedRealtime, uptime);
+ }
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+ pr.curCpuTime += st.rel_utime + st.rel_stime;
+ if (pr.lastCpuTime == 0) {
+ pr.lastCpuTime = pr.curCpuTime;
+ }
+ } else {
+ BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
+ if (ps == null || !ps.isActive()) {
+ st.batteryStats = ps = bstats.getProcessStatsLocked(
+ bstats.mapUid(st.uid), st.name,
+ elapsedRealtime, uptime);
+ }
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+ }
+ }
+ }
+
+ final int userTime = mProcessCpuTracker.getLastUserTime();
+ final int systemTime = mProcessCpuTracker.getLastSystemTime();
+ final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
+ final int irqTime = mProcessCpuTracker.getLastIrqTime();
+ final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
+ final int idleTime = mProcessCpuTracker.getLastIdleTime();
+ bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime,
+ systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
+ }
+ }
+
+ if (mLastWriteTime < (now - BATTERY_STATS_TIME)) {
+ mLastWriteTime = now;
+ mService.mBatteryStatsService.scheduleWriteToDisk();
+ }
+ }
+ }
+ }
+
+ long getCpuTimeForPid(int pid) {
+ synchronized (mProcessCpuTracker) {
+ return mProcessCpuTracker.getCpuTimeForPid(pid);
+ }
+ }
+
+ List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) {
+ synchronized (mProcessCpuTracker) {
+ return mProcessCpuTracker.getStats(st -> predicate.test(st));
+ }
+ }
+
+ void forAllCpuStats(Consumer<ProcessCpuTracker.Stats> consumer) {
+ synchronized (mProcessCpuTracker) {
+ final int numOfStats = mProcessCpuTracker.countStats();
+ for (int i = 0; i < numOfStats; i++) {
+ consumer.accept(mProcessCpuTracker.getStats(i));
+ }
+ }
+ }
+
+ private class ProcessCpuThread extends Thread {
+ ProcessCpuThread(String name) {
+ super(name);
+ }
+
+ @Override
+ public void run() {
+ synchronized (mProcessCpuTracker) {
+ mProcessCpuInitLatch.countDown();
+ mProcessCpuTracker.init();
+ }
+ while (true) {
+ try {
+ try {
+ synchronized (this) {
+ final long now = SystemClock.uptimeMillis();
+ long nextCpuDelay = (mLastCpuTime.get() + MONITOR_CPU_MAX_TIME) - now;
+ long nextWriteDelay = (mLastWriteTime + BATTERY_STATS_TIME) - now;
+ //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
+ // + ", write delay=" + nextWriteDelay);
+ if (nextWriteDelay < nextCpuDelay) {
+ nextCpuDelay = nextWriteDelay;
+ }
+ if (nextCpuDelay > 0) {
+ mProcessCpuMutexFree.set(true);
+ this.wait(nextCpuDelay);
+ }
+ }
+ } catch (InterruptedException e) {
+ }
+ updateCpuStatsNow();
+ } catch (Exception e) {
+ Slog.e(TAG, "Unexpected exception collecting process stats", e);
+ }
+ }
+ }
+ }
+
+ class CpuBinder extends Binder {
+ private final PriorityDump.PriorityDumper mPriorityDumper =
+ new PriorityDump.PriorityDumper() {
+ @Override
+ public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
+ boolean asProto) {
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mService.mContext, "cpuinfo", pw)) {
+ return;
+ }
+ synchronized (mProcessCpuTracker) {
+ if (asProto) {
+ mProcessCpuTracker.dumpProto(fd);
+ return;
+ }
+ pw.print(mProcessCpuTracker.printCurrentLoad());
+ pw.print(mProcessCpuTracker.printCurrentState(
+ SystemClock.uptimeMillis()));
+ }
+ }
+ };
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ PriorityDump.dump(mPriorityDumper, fd, pw, args);
+ }
+ }
+
+ void setCpuInfoService() {
+ if (MONITOR_CPU_USAGE) {
+ ServiceManager.addService("cpuinfo", new CpuBinder(),
+ /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
+ }
+ }
+
+ AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector) {
+ mService = service;
+ mBgHandler = new BgHandler(bgLooper);
+ mLowMemDetector = detector;
+ mProcessCpuThread = new ProcessCpuThread("CpuTracker");
+ }
+
+ void retrieveSettings() {
+ final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ActivityThread.currentApplication().getMainExecutor(),
+ mPssDelayConfigListener);
+ mPssDeferralTime = pssDeferralMs;
+ }
+
+ void onActivityManagerInternalAdded() {
+ mProcessCpuThread.start();
+ // Wait for the synchronized block started in mProcessCpuThread,
+ // so that any other access to mProcessCpuTracker from main thread
+ // will be blocked during mProcessCpuTracker initialization.
+ try {
+ mProcessCpuInitLatch.await();
+ } catch (InterruptedException e) {
+ Slog.wtf(TAG, "Interrupted wait during start", e);
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Interrupted wait during start");
+ }
+ }
+
+ void onActivityLaunched() {
+ // This is safe to force to the head of the queue because it relies only
+ // on refcounting to track begin/end of deferrals, not on actual
+ // message ordering. We don't care *what* activity is being
+ // launched; only that we're doing so.
+ if (mPssDeferralTime > 0) {
+ final Message msg = mBgHandler.obtainMessage(BgHandler.DEFER_PSS_MSG);
+ mBgHandler.sendMessageAtFrontOfQueue(msg);
+ }
+ }
+
+ @GuardedBy("mService")
+ ProfilerInfo setupProfilerInfoLocked(@NonNull IApplicationThread thread, ProcessRecord app,
+ ActiveInstrumentation instr) throws IOException, RemoteException {
+ ProfilerInfo profilerInfo = null;
+ String preBindAgent = null;
+ final String processName = app.processName;
+ if (mProfileData.getProfileApp() != null
+ && mProfileData.getProfileApp().equals(processName)) {
+ mProfileData.setProfileProc(app);
+ if (mProfileData.getProfilerInfo() != null) {
+ // Send a profiler info object to the app if either a file is given, or
+ // an agent should be loaded at bind-time.
+ boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().attachAgentDuringBind;
+ profilerInfo = needsInfo
+ ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
+ if (mProfileData.getProfilerInfo().agent != null) {
+ preBindAgent = mProfileData.getProfilerInfo().agent;
+ }
+ }
+ } else if (instr != null && instr.mProfileFile != null) {
+ profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
+ null, false);
+ }
+ if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
+ // We need to do a debuggable check here. See setAgentApp for why the check is
+ // postponed to here.
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ String agent = mAppAgentMap.get(processName);
+ // Do not overwrite already requested agent.
+ if (profilerInfo == null) {
+ profilerInfo = new ProfilerInfo(null, null, 0, false, false,
+ mAppAgentMap.get(processName), true);
+ } else if (profilerInfo.agent == null) {
+ profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
+ }
+ }
+ }
+
+ if (profilerInfo != null && profilerInfo.profileFd != null) {
+ profilerInfo.profileFd = profilerInfo.profileFd.dup();
+ if (TextUtils.equals(mProfileData.getProfileApp(), processName)
+ && mProfileData.getProfilerInfo() != null) {
+ clearProfilerLocked();
+ }
+ }
+
+ // Check if this is a secondary process that should be incorporated into some
+ // currently active instrumentation. (Note we do this AFTER all of the profiling
+ // stuff above because profiling can currently happen only in the primary
+ // instrumentation process.)
+ if (mService.mActiveInstrumentation.size() > 0 && instr == null) {
+ for (int i = mService.mActiveInstrumentation.size() - 1;
+ i >= 0 && app.getActiveInstrumentation() == null; i--) {
+ ActiveInstrumentation aInstr = mService.mActiveInstrumentation.get(i);
+ if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
+ if (aInstr.mTargetProcesses.length == 0) {
+ // This is the wildcard mode, where every process brought up for
+ // the target instrumentation should be included.
+ if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
+ app.setActiveInstrumentation(aInstr);
+ aInstr.mRunningProcesses.add(app);
+ }
+ } else {
+ for (String proc : aInstr.mTargetProcesses) {
+ if (proc.equals(app.processName)) {
+ app.setActiveInstrumentation(aInstr);
+ aInstr.mRunningProcesses.add(app);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // If we were asked to attach an agent on startup, do so now, before we're binding
+ // application code.
+ if (preBindAgent != null) {
+ thread.attachAgent(preBindAgent);
+ }
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ thread.attachStartupAgents(app.info.dataDir);
+ }
+ return profilerInfo;
+ }
+
+ @GuardedBy("mService")
+ void onCleanupApplicationRecordLocked(ProcessRecord app) {
+ mPendingPssProcesses.remove(app);
+ abortNextPssTime(app.procStateMemTracker);
+ }
+
+ @GuardedBy("mService")
+ void onAppDiedLocked(ProcessRecord app) {
+ if (mProfileData.getProfileProc() == app) {
+ clearProfilerLocked();
+ }
+ }
+
+ @GuardedBy("mService")
+ boolean dumpMemWatchProcessesLocked(PrintWriter pw, boolean needSep) {
+ if (mMemWatchProcesses.getMap().size() > 0) {
+ pw.println(" Mem watch processes:");
+ final ArrayMap<String, SparseArray<Pair<Long, String>>> procs =
+ mMemWatchProcesses.getMap();
+ for (int i = procs.size() - 1; i >= 0; i--) {
+ final String proc = procs.keyAt(i);
+ final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
+ for (int j = uids.size() - 1; j >= 0; j--) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ").append(proc).append('/');
+ UserHandle.formatUid(sb, uids.keyAt(j));
+ Pair<Long, String> val = uids.valueAt(j);
+ sb.append(": "); DebugUtils.sizeValueToString(val.first, sb);
+ if (val.second != null) {
+ sb.append(", report to ").append(val.second);
+ }
+ pw.println(sb.toString());
+ }
+ }
+ pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
+ pw.print(" mMemWatchDumpUri="); pw.println(mMemWatchDumpUri);
+ pw.print(" mMemWatchDumpPid="); pw.println(mMemWatchDumpPid);
+ pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
+ pw.print(" mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated);
+ }
+ return needSep;
+ }
+
+ @GuardedBy("mService")
+ boolean dumpProfileDataLocked(PrintWriter pw, String dumpPackage, boolean needSep) {
+ if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+ || (mProfileData.getProfilerInfo() != null
+ && (mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().profileFd != null))) {
+ if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mProfileApp=" + mProfileData.getProfileApp()
+ + " mProfileProc=" + mProfileData.getProfileProc());
+ if (mProfileData.getProfilerInfo() != null) {
+ pw.println(" mProfileFile=" + mProfileData.getProfilerInfo().profileFile
+ + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
+ pw.println(" mSamplingInterval="
+ + mProfileData.getProfilerInfo().samplingInterval
+ + " mAutoStopProfiler="
+ + mProfileData.getProfilerInfo().autoStopProfiler
+ + " mStreamingOutput="
+ + mProfileData.getProfilerInfo().streamingOutput);
+ pw.println(" mProfileType=" + mProfileType);
+ }
+ }
+ }
+ return needSep;
+ }
+
+ @GuardedBy("mService")
+ void dumpLastMemoryLevelLocked(PrintWriter pw) {
+ switch (mLastMemoryLevel) {
+ case ProcessStats.ADJ_MEM_FACTOR_NORMAL:
+ pw.println("normal)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+ pw.println("moderate)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ pw.println("low)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ pw.println("critical)");
+ break;
+ default:
+ pw.print(mLastMemoryLevel);
+ pw.println(")");
+ break;
+ }
+ }
+
+ @GuardedBy("mService")
+ void dumpMemoryLevelsLocked(PrintWriter pw) {
+ pw.println(" mAllowLowerMemLevel=" + mAllowLowerMemLevel
+ + " mLastMemoryLevel=" + mLastMemoryLevel
+ + " mLastNumProcesses=" + mLastNumProcesses);
+ }
+
+ @GuardedBy("mService")
+ void writeMemWatchProcessToProtoLocked(ProtoOutputStream proto) {
+ if (mMemWatchProcesses.getMap().size() > 0) {
+ final long token = proto.start(
+ ActivityManagerServiceDumpProcessesProto.MEM_WATCH_PROCESSES);
+ ArrayMap<String, SparseArray<Pair<Long, String>>> procs = mMemWatchProcesses.getMap();
+ for (int i = 0; i < procs.size(); i++) {
+ final String proc = procs.keyAt(i);
+ final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
+ final long ptoken = proto.start(
+ ActivityManagerServiceDumpProcessesProto.MemWatchProcess.PROCS);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Process.NAME,
+ proc);
+ for (int j = uids.size() - 1; j >= 0; j--) {
+ final long utoken = proto.start(ActivityManagerServiceDumpProcessesProto
+ .MemWatchProcess.Process.MEM_STATS);
+ Pair<Long, String> val = uids.valueAt(j);
+ proto.write(ActivityManagerServiceDumpProcessesProto
+ .MemWatchProcess.Process.MemStats.UID, uids.keyAt(j));
+ proto.write(ActivityManagerServiceDumpProcessesProto
+ .MemWatchProcess.Process.MemStats.SIZE,
+ DebugUtils.sizeValueToString(val.first, new StringBuilder()));
+ proto.write(ActivityManagerServiceDumpProcessesProto
+ .MemWatchProcess.Process.MemStats.REPORT_TO, val.second);
+ proto.end(utoken);
+ }
+ proto.end(ptoken);
+ }
+
+ final long dtoken = proto.start(
+ ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME,
+ mMemWatchDumpProcName);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI,
+ mMemWatchDumpUri.toString());
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID,
+ mMemWatchDumpPid);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID,
+ mMemWatchDumpUid);
+ proto.write(
+ ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED,
+ mMemWatchIsUserInitiated);
+ proto.end(dtoken);
+
+ proto.end(token);
+ }
+ }
+
+ @GuardedBy("mService")
+ void writeProfileDataToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
+ if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+ || (mProfileData.getProfilerInfo() != null
+ && (mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().profileFd != null))) {
+ if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
+ final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE);
+ proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME,
+ mProfileData.getProfileApp());
+ mProfileData.getProfileProc().dumpDebug(proto,
+ ActivityManagerServiceDumpProcessesProto.Profile.PROC);
+ if (mProfileData.getProfilerInfo() != null) {
+ mProfileData.getProfilerInfo().dumpDebug(proto,
+ ActivityManagerServiceDumpProcessesProto.Profile.INFO);
+ proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE,
+ mProfileType);
+ }
+ proto.end(token);
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void writeMemoryLevelsToProtoLocked(ProtoOutputStream proto) {
+ proto.write(ActivityManagerServiceDumpProcessesProto.ALLOW_LOWER_MEM_LEVEL,
+ mAllowLowerMemLevel);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LAST_MEMORY_LEVEL, mLastMemoryLevel);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LAST_NUM_PROCESSES, mLastNumProcesses);
+ }
+
+ void printCurrentCpuState(StringBuilder report, long time) {
+ synchronized (mProcessCpuTracker) {
+ report.append(mProcessCpuTracker.printCurrentState(time));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 39f79ca..692b3f1 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -376,7 +376,8 @@
for (int uid : uidsToRemove) {
FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, -1, uid,
FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
- mStats.removeIsolatedUidLocked(uid);
+ mStats.removeIsolatedUidLocked(uid, SystemClock.elapsedRealtime(),
+ SystemClock.uptimeMillis());
}
mStats.clearPendingRemovedUids();
}
@@ -473,11 +474,15 @@
final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtimeUs = elapsedRealtime * 1000;
+ final long uptimeUs = uptime * 1000;
synchronized (mStats) {
mStats.addHistoryEventLocked(
- SystemClock.elapsedRealtime(),
- SystemClock.uptimeMillis(),
+ elapsedRealtime,
+ uptime,
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
reason, 0);
@@ -490,17 +495,17 @@
}
if ((updateFlags & UPDATE_ALL) != 0) {
- mStats.updateKernelWakelocksLocked();
- mStats.updateKernelMemoryBandwidthLocked();
+ mStats.updateKernelWakelocksLocked(elapsedRealtimeUs);
+ mStats.updateKernelMemoryBandwidthLocked(elapsedRealtimeUs);
}
if ((updateFlags & UPDATE_RPM) != 0) {
- mStats.updateRpmStatsLocked();
+ mStats.updateRpmStatsLocked(elapsedRealtimeUs);
}
if (bluetoothInfo != null) {
if (bluetoothInfo.isValid()) {
- mStats.updateBluetoothStateLocked(bluetoothInfo);
+ mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime);
} else {
Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo);
}
@@ -512,7 +517,7 @@
if (wifiInfo != null) {
if (wifiInfo.isValid()) {
- mStats.updateWifiState(extractDeltaLocked(wifiInfo));
+ mStats.updateWifiState(extractDeltaLocked(wifiInfo), elapsedRealtime, uptime);
} else {
Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
}
@@ -520,7 +525,7 @@
if (modemInfo != null) {
if (modemInfo.isValid()) {
- mStats.updateMobileRadioState(modemInfo);
+ mStats.updateMobileRadioState(modemInfo, elapsedRealtime, uptime);
} else {
Slog.w(TAG, "modem info is invalid: " + modemInfo);
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d72998b..f427532 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -25,6 +25,7 @@
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
@@ -62,7 +63,9 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.ParseUtils;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
+import com.android.server.Watchdog;
import java.io.File;
import java.io.FileDescriptor;
@@ -76,6 +79,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -86,7 +90,8 @@
public final class BatteryStatsService extends IBatteryStats.Stub
implements PowerManagerInternal.LowPowerModeListener,
BatteryStatsImpl.PlatformIdleStateCallback,
- BatteryStatsImpl.RailEnergyDataCallback {
+ BatteryStatsImpl.RailEnergyDataCallback,
+ Watchdog.Monitor {
static final String TAG = "BatteryStatsService";
static final boolean DBG = false;
@@ -110,6 +115,10 @@
private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
private static final int MAX_LOW_POWER_STATS_SIZE = 4096;
+ private final HandlerThread mHandlerThread;
+ private final Handler mHandler;
+ private final Object mLock = new Object();
+
/**
* Replaces the information in the given rpmStats with up-to-date information.
*/
@@ -190,6 +199,9 @@
return (umi != null) ? umi.getUserIds() : null;
}
};
+ mHandlerThread = new HandlerThread("batterystats-handler");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
mStats = new BatteryStatsImpl(systemDir, handler, this,
this, mUserManagerUserInfoProvider);
mWorker = new BatteryExternalStatsWorker(context, mStats);
@@ -206,6 +218,7 @@
public void systemServicesReady() {
mStats.systemServicesReady(mContext);
+ Watchdog.getInstance().addMonitor(this);
}
private final class LocalService extends BatteryStatsInternal {
@@ -228,8 +241,20 @@
@Override
public void noteBinderCallStats(int workSourceUid, long incrementatCallCount,
Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) {
- mStats.noteBinderCallStats(workSourceUid, incrementatCallCount, callStats,
- binderThreadNativeTids);
+ synchronized (BatteryStatsService.this.mLock) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ mStats::noteBinderCallStats, workSourceUid, incrementatCallCount,
+ callStats, binderThreadNativeTids,
+ SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()));
+ }
+ }
+ }
+
+ @Override
+ public void monitor() {
+ synchronized (mLock) {
+ }
+ synchronized (mStats) {
}
}
@@ -250,6 +275,19 @@
awaitUninterruptibly(mWorker.scheduleSync(reason, flags));
}
+ private void awaitCompletion() {
+ synchronized (mLock) {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mHandler.post(() -> {
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
/**
* At the time when the constructor runs, the power manager has not yet been
* initialized. So we initialize the low power observer later.
@@ -259,8 +297,8 @@
powerMgr.registerLowPowerModeObserver(this);
synchronized (mStats) {
mStats.notePowerSaveModeLocked(
- powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
- .batterySaverEnabled);
+ powerMgr.getLowPowerState(ServiceType.BATTERY_STATS).batterySaverEnabled,
+ SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
}
(new WakeupReasonThread()).start();
}
@@ -268,6 +306,9 @@
public void shutdown() {
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
+ // Drain the handler queue to make sure we've handled all pending works.
+ awaitCompletion();
+
syncStats("shutdown", BatteryExternalStatsWorker.UPDATE_ALL);
synchronized (mStats) {
@@ -293,9 +334,16 @@
}
@Override
- public void onLowPowerModeChanged(PowerSaveState result) {
- synchronized (mStats) {
- mStats.notePowerSaveModeLocked(result.batterySaverEnabled);
+ public void onLowPowerModeChanged(final PowerSaveState result) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePowerSaveModeLocked(result.batterySaverEnabled,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@@ -313,7 +361,12 @@
* object to update with the latest info, then write to disk.
*/
public void scheduleWriteToDisk() {
- mWorker.scheduleWrite();
+ synchronized (mLock) {
+ // We still schedule it on the handler so we'll have all existing pending works done.
+ mHandler.post(() -> {
+ mWorker.scheduleWrite();
+ });
+ }
}
// These are for direct use by the activity manager...
@@ -321,70 +374,124 @@
/**
* Remove a UID from the BatteryStats and BatteryStats' external dependencies.
*/
- void removeUid(int uid) {
- synchronized (mStats) {
- mStats.removeUidStatsLocked(uid);
+ void removeUid(final int uid) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.removeUidStatsLocked(uid, elapsedRealtime);
+ }
+ });
}
}
- void onCleanupUser(int userId) {
- synchronized (mStats) {
- mStats.onCleanupUserLocked(userId);
+ void onCleanupUser(final int userId) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.onCleanupUserLocked(userId, elapsedRealtime);
+ }
+ });
}
}
- void onUserRemoved(int userId) {
- synchronized (mStats) {
- mStats.onUserRemovedLocked(userId);
+ void onUserRemoved(final int userId) {
+ synchronized (mLock) {
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.onUserRemovedLocked(userId);
+ }
+ });
}
}
- void addIsolatedUid(int isolatedUid, int appUid) {
- synchronized (mStats) {
- mStats.addIsolatedUidLocked(isolatedUid, appUid);
+ void addIsolatedUid(final int isolatedUid, final int appUid) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.addIsolatedUidLocked(isolatedUid, appUid, elapsedRealtime, uptime);
+ }
+ });
}
}
- void removeIsolatedUid(int isolatedUid, int appUid) {
- synchronized (mStats) {
- mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid);
+ void removeIsolatedUid(final int isolatedUid, final int appUid) {
+ synchronized (mLock) {
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid);
+ }
+ });
}
}
- void noteProcessStart(String name, int uid) {
- synchronized (mStats) {
- mStats.noteProcessStartLocked(name, uid);
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
- FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__STARTED);
+ void noteProcessStart(final String name, final int uid) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteProcessStartLocked(name, uid, elapsedRealtime, uptime);
+ }
+ });
}
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
+ FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__STARTED);
}
void noteProcessCrash(String name, int uid) {
- synchronized (mStats) {
- mStats.noteProcessCrashLocked(name, uid);
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
- FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteProcessCrashLocked(name, uid, elapsedRealtime, uptime);
+ }
+ });
}
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
+ FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED);
}
void noteProcessAnr(String name, int uid) {
- synchronized (mStats) {
- mStats.noteProcessAnrLocked(name, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteProcessAnrLocked(name, uid, elapsedRealtime, uptime);
+ }
+ });
}
}
void noteProcessFinish(String name, int uid) {
- synchronized (mStats) {
- mStats.noteProcessFinishLocked(name, uid);
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
- FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__FINISHED);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteProcessFinishLocked(name, uid, elapsedRealtime, uptime);
+ }
+ });
}
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name,
+ FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__FINISHED);
}
/** @param state Process state from ActivityManager.java. */
void noteUidProcessState(int uid, int state) {
- synchronized (mStats) {
- mStats.noteUidProcessStateLocked(uid, state);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteUidProcessStateLocked(uid, state, elapsedRealtime, uptime);
+ }
+ });
}
}
@@ -396,6 +503,9 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
+ // Drain the handler queue to make sure we've handled all pending works, so we'll get
+ // an accurate stats.
+ awaitCompletion();
syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
@@ -411,6 +521,9 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
+ // Drain the handler queue to make sure we've handled all pending works, so we'll get
+ // an accurate stats.
+ awaitCompletion();
syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
@@ -446,579 +559,1015 @@
}
}
- public void noteEvent(int code, String name, int uid) {
+ public void noteEvent(final int code, final String name, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteEventLocked(code, name, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteEventLocked(code, name, uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteSyncStart(String name, int uid) {
+ public void noteSyncStart(final String name, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteSyncStartLocked(name, uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null,
- name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteSyncStartLocked(name, uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null,
+ name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__ON);
+ });
}
}
- public void noteSyncFinish(String name, int uid) {
+ public void noteSyncFinish(final String name, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteSyncFinishLocked(name, uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null,
- name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteSyncFinishLocked(name, uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null,
+ name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__OFF);
+ });
}
}
/** A scheduled job was started. */
- public void noteJobStart(String name, int uid) {
+ public void noteJobStart(final String name, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteJobStartLocked(name, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteJobStartLocked(name, uid, elapsedRealtime, uptime);
+ }
+ });
}
}
/** A scheduled job was finished. */
- public void noteJobFinish(String name, int uid, int stopReason) {
+ public void noteJobFinish(final String name, final int uid, final int stopReason) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteJobFinishLocked(name, uid, stopReason);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteJobFinishLocked(name, uid, stopReason, elapsedRealtime, uptime);
+ }
+ });
}
}
- void noteJobsDeferred(int uid, int numDeferred, long sinceLast) {
+ void noteJobsDeferred(final int uid, final int numDeferred, final long sinceLast) {
// No need to enforce calling permission, as it is called from an internal interface
- synchronized (mStats) {
- mStats.noteJobsDeferredLocked(uid, numDeferred, sinceLast);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteJobsDeferredLocked(uid, numDeferred, sinceLast,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWakupAlarm(String name, int uid, WorkSource workSource, String tag) {
+ public void noteWakupAlarm(final String name, final int uid, final WorkSource workSource,
+ final String tag) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWakupAlarmLocked(name, uid, workSource, tag);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWakupAlarmLocked(name, uid, workSource, tag,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteAlarmStart(String name, WorkSource workSource, int uid) {
+ public void noteAlarmStart(final String name, final WorkSource workSource, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteAlarmStartLocked(name, workSource, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteAlarmStartLocked(name, workSource, uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteAlarmFinish(String name, WorkSource workSource, int uid) {
+ public void noteAlarmFinish(final String name, final WorkSource workSource, final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteAlarmFinishLocked(name, workSource, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteAlarmFinishLocked(name, workSource, uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
- boolean unimportantForLogging) {
+ public void noteStartWakelock(final int uid, final int pid, final String name,
+ final String historyName, final int type, final boolean unimportantForLogging) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStartWakeLocked(uid, pid, null, name, historyName, type,
- unimportantForLogging, SystemClock.elapsedRealtime(),
- SystemClock.uptimeMillis());
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStartWakeLocked(uid, pid, null, name, historyName, type,
+ unimportantForLogging, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) {
+ public void noteStopWakelock(final int uid, final int pid, final String name,
+ final String historyName, final int type) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStopWakeLocked(uid, pid, null, name, historyName, type,
- SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStopWakeLocked(uid, pid, null, name, historyName, type,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
- String historyName, int type, boolean unimportantForLogging) {
+ public void noteStartWakelockFromSource(final WorkSource ws, final int pid, final String name,
+ final String historyName, final int type, final boolean unimportantForLogging) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
- type, unimportantForLogging);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
+ type, unimportantForLogging, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name,
- String historyName, int type, WorkSource newWs, int newPid, String newName,
- String newHistoryName, int newType, boolean newUnimportantForLogging) {
+ public void noteChangeWakelockFromSource(final WorkSource ws, final int pid, final String name,
+ final String historyName, final int type, final WorkSource newWs, final int newPid,
+ final String newName, final String newHistoryName, final int newType,
+ final boolean newUnimportantForLogging) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
- newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
+ newWs, newPid, newName, newHistoryName, newType,
+ newUnimportantForLogging, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName,
- int type) {
+ public void noteStopWakelockFromSource(final WorkSource ws, final int pid, final String name,
+ final String historyName, final int type) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
+ public void noteLongPartialWakelockStart(final String name, final String historyName,
+ final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteLongPartialWakelockStart(name, historyName, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockStart(name, historyName, uid,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteLongPartialWakelockStartFromSource(String name, String historyName,
- WorkSource workSource) {
+ public void noteLongPartialWakelockStartFromSource(final String name, final String historyName,
+ final WorkSource workSource) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
+ public void noteLongPartialWakelockFinish(final String name, final String historyName,
+ final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteLongPartialWakelockFinish(name, historyName, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockFinish(name, historyName, uid,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
- WorkSource workSource) {
+ public void noteLongPartialWakelockFinishFromSource(final String name, final String historyName,
+ final WorkSource workSource) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteStartSensor(int uid, int sensor) {
+ public void noteStartSensor(final int uid, final int sensor) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStartSensorLocked(uid, sensor);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null,
- sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStartSensorLocked(uid, sensor, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid,
+ null, sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON);
+ });
}
}
- public void noteStopSensor(int uid, int sensor) {
+ public void noteStopSensor(final int uid, final int sensor) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteStopSensorLocked(uid, sensor);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null,
- sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteStopSensorLocked(uid, sensor, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid,
+ null, sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteVibratorOn(int uid, long durationMillis) {
+ public void noteVibratorOn(final int uid, final long durationMillis) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteVibratorOnLocked(uid, durationMillis);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteVibratorOnLocked(uid, durationMillis, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteVibratorOff(int uid) {
+ public void noteVibratorOff(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteVibratorOffLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteVibratorOffLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteGpsChanged(WorkSource oldWs, WorkSource newWs) {
+ public void noteGpsChanged(final WorkSource oldWs, final WorkSource newWs) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteGpsChangedLocked(oldWs, newWs);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteGpsChangedLocked(oldWs, newWs, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteGpsSignalQuality(int signalLevel) {
- synchronized (mStats) {
- mStats.noteGpsSignalQualityLocked(signalLevel);
+ public void noteGpsSignalQuality(final int signalLevel) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteGpsSignalQualityLocked(signalLevel, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteScreenState(int state) {
+ public void noteScreenState(final int state) {
enforceCallingPermission();
- if (DBG) Slog.d(TAG, "begin noteScreenState");
- synchronized (mStats) {
- FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED, state);
-
- mStats.noteScreenStateLocked(state);
- }
- if (DBG) Slog.d(TAG, "end noteScreenState");
- }
-
- public void noteScreenBrightness(int brightness) {
- enforceCallingPermission();
- synchronized (mStats) {
- FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness);
- mStats.noteScreenBrightnessLocked(brightness);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ final long currentTime = System.currentTimeMillis();
+ mHandler.post(() -> {
+ if (DBG) Slog.d(TAG, "begin noteScreenState");
+ synchronized (mStats) {
+ mStats.noteScreenStateLocked(state, elapsedRealtime, uptime, currentTime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED, state);
+ if (DBG) Slog.d(TAG, "end noteScreenState");
+ });
}
}
- public void noteUserActivity(int uid, int event) {
+ public void noteScreenBrightness(final int brightness) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteUserActivityLocked(uid, event);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteScreenBrightnessLocked(brightness, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness);
+ });
}
}
- public void noteWakeUp(String reason, int reasonUid) {
+ public void noteUserActivity(final int uid, final int event) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWakeUpLocked(reason, reasonUid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteUserActivityLocked(uid, event, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteInteractive(boolean interactive) {
+ public void noteWakeUp(final String reason, final int reasonUid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteInteractiveLocked(interactive);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWakeUpLocked(reason, reasonUid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteConnectivityChanged(int type, String extra) {
+ public void noteInteractive(final boolean interactive) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteConnectivityChangedLocked(type, extra);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteInteractiveLocked(interactive, elapsedRealtime);
+ }
+ });
}
}
- public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
+ public void noteConnectivityChanged(final int type, final String extra) {
enforceCallingPermission();
- final boolean update;
- synchronized (mStats) {
- update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteConnectivityChangedLocked(type, extra, elapsedRealtime, uptime);
+ }
+ });
}
+ }
- if (update) {
- mWorker.scheduleSync("modem-data", BatteryExternalStatsWorker.UPDATE_RADIO);
+ public void noteMobileRadioPowerState(final int powerState, final long timestampNs,
+ final int uid) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ final boolean update;
+ synchronized (mStats) {
+ update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
+ elapsedRealtime, uptime);
+ }
+
+ if (update) {
+ mWorker.scheduleSync("modem-data", BatteryExternalStatsWorker.UPDATE_RADIO);
+ }
+ });
}
}
public void notePhoneOn() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePhoneOnLocked();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePhoneOnLocked(elapsedRealtime, uptime);
+ }
+ });
}
}
public void notePhoneOff() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePhoneOffLocked();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePhoneOffLocked(elapsedRealtime, uptime);
+ }
+ });
}
}
- public void notePhoneSignalStrength(SignalStrength signalStrength) {
+ public void notePhoneSignalStrength(final SignalStrength signalStrength) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePhoneSignalStrengthLocked(signalStrength);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePhoneSignalStrengthLocked(signalStrength, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType) {
+ public void notePhoneDataConnectionState(final int dataType, final boolean hasData,
+ final int serviceType) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void notePhoneState(int state) {
+ public void notePhoneState(final int state) {
enforceCallingPermission();
- int simState = mContext.getSystemService(TelephonyManager.class).getSimState();
- synchronized (mStats) {
- mStats.notePhoneStateLocked(state, simState);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ int simState = mContext.getSystemService(TelephonyManager.class).getSimState();
+ synchronized (mStats) {
+ mStats.notePhoneStateLocked(state, simState, elapsedRealtime, uptime);
+ }
+ });
}
}
public void noteWifiOn() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiOnLocked();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiOnLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED,
+ FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON);
+ });
}
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED,
- FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON);
}
public void noteWifiOff() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiOffLocked();
- }
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED,
- FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__OFF);
- }
-
- public void noteStartAudio(int uid) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteAudioOnLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null,
- FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiOffLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED,
+ FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteStopAudio(int uid) {
+ public void noteStartAudio(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteAudioOffLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null,
- FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteAudioOnLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__ON);
+ });
}
}
- public void noteStartVideo(int uid) {
+ public void noteStopAudio(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteVideoOnLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid,
- null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteAudioOffLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteStopVideo(int uid) {
+ public void noteStartVideo(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteVideoOffLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid,
- null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteVideoOnLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED,
+ uid, null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON);
+ });
+ }
+ }
+
+ public void noteStopVideo(final int uid) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteVideoOffLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED,
+ uid, null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF);
+ });
}
}
public void noteResetAudio() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteResetAudioLocked();
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, -1, null,
- FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__RESET);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteResetAudioLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, -1, null,
+ FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__RESET);
+ });
}
}
public void noteResetVideo() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteResetVideoLocked();
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, -1,
- null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteResetVideoLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, -1,
+ null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET);
+ });
}
}
- public void noteFlashlightOn(int uid) {
+ public void noteFlashlightOn(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFlashlightOnLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid,
- null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFlashlightOnLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON);
+ });
}
}
- public void noteFlashlightOff(int uid) {
+ public void noteFlashlightOff(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFlashlightOffLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid,
- null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFlashlightOffLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteStartCamera(int uid) {
+ public void noteStartCamera(final int uid) {
enforceCallingPermission();
if (DBG) Slog.d(TAG, "begin noteStartCamera");
- synchronized (mStats) {
- mStats.noteCameraOnLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null,
- FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__ON);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteCameraOnLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__ON);
+ });
}
if (DBG) Slog.d(TAG, "end noteStartCamera");
}
- public void noteStopCamera(int uid) {
+ public void noteStopCamera(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteCameraOffLocked(uid);
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null,
- FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteCameraOffLocked(uid, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid,
+ null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__OFF);
+ });
}
}
public void noteResetCamera() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteResetCameraLocked();
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, -1, null,
- FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__RESET);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteResetCameraLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, -1,
+ null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__RESET);
+ });
}
}
public void noteResetFlashlight() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteResetFlashlightLocked();
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, -1,
- null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteResetFlashlightLocked(elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, -1,
+ null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET);
+ });
}
}
@Override
- public void noteWifiRadioPowerState(int powerState, long tsNanos, int uid) {
+ public void noteWifiRadioPowerState(final int powerState, final long tsNanos, final int uid) {
enforceCallingPermission();
-
- // There was a change in WiFi power state.
- // Collect data now for the past activity.
- synchronized (mStats) {
- if (mStats.isOnBattery()) {
- final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH ||
- powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
- : "inactive";
- mWorker.scheduleSync("wifi-data: " + type, BatteryExternalStatsWorker.UPDATE_WIFI);
- }
- mStats.noteWifiRadioPowerState(powerState, tsNanos, uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ // There was a change in WiFi power state.
+ // Collect data now for the past activity.
+ synchronized (mStats) {
+ if (mStats.isOnBattery()) {
+ final String type =
+ (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+ || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM)
+ ? "active" : "inactive";
+ mWorker.scheduleSync("wifi-data: " + type,
+ BatteryExternalStatsWorker.UPDATE_WIFI);
+ }
+ mStats.noteWifiRadioPowerState(powerState, tsNanos, uid,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiRunning(WorkSource ws) {
+ public void noteWifiRunning(final WorkSource ws) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiRunningLocked(ws);
- }
- // TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too.
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
- ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON);
- }
-
- public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiRunningChangedLocked(oldWs, newWs);
- }
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
- newWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON);
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
- oldWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF);
- }
-
- public void noteWifiStopped(WorkSource ws) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiStoppedLocked(ws);
- }
- FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
- ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF);
- }
-
- public void noteWifiState(int wifiState, String accessPoint) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiStateLocked(wifiState, accessPoint);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiRunningLocked(ws, elapsedRealtime, uptime);
+ }
+ // TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too.
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
+ ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON);
+ });
}
}
- public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) {
+ public void noteWifiRunningChanged(final WorkSource oldWs, final WorkSource newWs) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiRunningChangedLocked(oldWs, newWs, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
+ newWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON);
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
+ oldWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteWifiRssiChanged(int newRssi) {
+ public void noteWifiStopped(final WorkSource ws) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiRssiChangedLocked(newRssi);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiStoppedLocked(ws, elapsedRealtime, uptime);
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
+ ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF);
+ });
}
}
- public void noteFullWifiLockAcquired(int uid) {
+ public void noteWifiState(final int wifiState, final String accessPoint) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFullWifiLockAcquiredLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiStateLocked(wifiState, accessPoint, elapsedRealtime);
+ }
+ });
}
}
- public void noteFullWifiLockReleased(int uid) {
+ public void noteWifiSupplicantStateChanged(final int supplState, final boolean failedAuth) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFullWifiLockReleasedLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiScanStarted(int uid) {
+ public void noteWifiRssiChanged(final int newRssi) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiScanStartedLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiRssiChangedLocked(newRssi, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiScanStopped(int uid) {
+ public void noteFullWifiLockAcquired(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiScanStoppedLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFullWifiLockAcquiredLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiMulticastEnabled(int uid) {
+ public void noteFullWifiLockReleased(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiMulticastEnabledLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFullWifiLockReleasedLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiMulticastDisabled(int uid) {
+ public void noteWifiScanStarted(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiMulticastDisabledLocked(uid);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiScanStartedLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
+ public void noteWifiScanStopped(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiScanStoppedLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
+ public void noteWifiMulticastEnabled(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiMulticastEnabledLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiScanStartedFromSource(WorkSource ws) {
+ public void noteWifiMulticastDisabled(final int uid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiScanStartedFromSourceLocked(ws);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiMulticastDisabledLocked(uid, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiScanStoppedFromSource(WorkSource ws) {
+ public void noteFullWifiLockAcquiredFromSource(final WorkSource ws) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiScanStoppedFromSourceLocked(ws);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFullWifiLockAcquiredFromSourceLocked(ws, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
+ public void noteFullWifiLockReleasedFromSource(final WorkSource ws) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteFullWifiLockReleasedFromSourceLocked(ws, elapsedRealtime, uptime);
+ }
+ });
}
}
- public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
+ public void noteWifiScanStartedFromSource(final WorkSource ws) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiScanStartedFromSourceLocked(ws, elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ public void noteWifiScanStoppedFromSource(final WorkSource ws) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ public void noteWifiBatchedScanStartedFromSource(final WorkSource ws, final int csph) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
+ elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ public void noteWifiBatchedScanStoppedFromSource(final WorkSource ws) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteNetworkInterfaceType(String iface, int networkType) {
+ public void noteNetworkInterfaceType(final String iface, final int networkType) {
enforceCallingPermission();
- mStats.noteNetworkInterfaceType(iface, networkType);
+ synchronized (mLock) {
+ mHandler.post(() -> {
+ mStats.noteNetworkInterfaceType(iface, networkType);
+ });
+ }
}
@Override
@@ -1027,66 +1576,119 @@
// During device boot, qtaguid isn't enabled until after the inital
// loading of battery stats. Now that they're enabled, take our initial
// snapshot for future delta calculation.
- mWorker.scheduleSync("network-stats-enabled",
- BatteryExternalStatsWorker.UPDATE_RADIO | BatteryExternalStatsWorker.UPDATE_WIFI);
- }
-
- @Override
- public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid);
- }
- }
-
- public void notePackageInstalled(String pkgName, long versionCode) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePackageInstalledLocked(pkgName, versionCode);
- }
- }
-
- public void notePackageUninstalled(String pkgName) {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.notePackageUninstalledLocked(pkgName);
+ synchronized (mLock) {
+ // Still schedule it on the handler to make sure we have existing pending works done
+ mHandler.post(() -> {
+ mWorker.scheduleSync("network-stats-enabled",
+ BatteryExternalStatsWorker.UPDATE_RADIO
+ | BatteryExternalStatsWorker.UPDATE_WIFI);
+ });
}
}
@Override
- public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) {
+ public void noteDeviceIdleMode(final int mode, final String activeReason, final int activeUid) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid,
+ elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ public void notePackageInstalled(final String pkgName, final long versionCode) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePackageInstalledLocked(pkgName, versionCode,
+ elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ public void notePackageUninstalled(final String pkgName) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.notePackageUninstalledLocked(pkgName, elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteBleScanStopped(WorkSource ws, boolean isUnoptimized) {
+ public void noteBleScanStarted(final WorkSource ws, final boolean isUnoptimized) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
+ elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void noteBleScanStopped(final WorkSource ws, final boolean isUnoptimized) {
+ enforceCallingPermission();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
+ uptime, elapsedRealtime);
+ }
+ });
}
}
@Override
public void noteResetBleScan() {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteResetBluetoothScanLocked();
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteResetBluetoothScanLocked(elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteBleScanResults(WorkSource ws, int numNewResults) {
+ public void noteBleScanResults(final WorkSource ws, final int numNewResults) {
enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
+ elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteWifiControllerActivity(WifiActivityEnergyInfo info) {
+ public void noteWifiControllerActivity(final WifiActivityEnergyInfo info) {
enforceCallingPermission();
if (info == null || !info.isValid()) {
@@ -1094,24 +1696,36 @@
return;
}
- mStats.updateWifiState(info);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ mStats.updateWifiState(info, elapsedRealtime, uptime);
+ });
+ }
}
@Override
- public void noteBluetoothControllerActivity(BluetoothActivityEnergyInfo info) {
+ public void noteBluetoothControllerActivity(final BluetoothActivityEnergyInfo info) {
enforceCallingPermission();
if (info == null || !info.isValid()) {
Slog.e(TAG, "invalid bluetooth data given: " + info);
return;
}
- synchronized (mStats) {
- mStats.updateBluetoothStateLocked(info);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.updateBluetoothStateLocked(info, elapsedRealtime, uptime);
+ }
+ });
}
}
@Override
- public void noteModemControllerActivity(ModemActivityInfo info) {
+ public void noteModemControllerActivity(final ModemActivityInfo info) {
enforceCallingPermission();
if (info == null || !info.isValid()) {
@@ -1119,7 +1733,13 @@
return;
}
- mStats.updateMobileRadioState(info);
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ mStats.updateMobileRadioState(info, elapsedRealtime, uptime);
+ });
+ }
}
public boolean isOnBattery() {
@@ -1132,32 +1752,43 @@
final int chargeFullUAh, final long chargeTimeToFullSeconds) {
enforceCallingPermission();
- // BatteryService calls us here and we may update external state. It would be wrong
- // to block such a low level service like BatteryService on external stats like WiFi.
- mWorker.scheduleRunnable(() -> {
- synchronized (mStats) {
- final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status);
- if (mStats.isOnBattery() == onBattery) {
- // The battery state has not changed, so we don't need to sync external
- // stats immediately.
- mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
- chargeUAh, chargeFullUAh, chargeTimeToFullSeconds);
- return;
- }
- }
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ final long currentTime = System.currentTimeMillis();
+ // We still schedule this task over the handler thread to make sure we've had
+ // all existing pending work handled before setting the battery state
+ mHandler.post(() -> {
+ // BatteryService calls us here and we may update external state. It would be wrong
+ // to block such a low level service like BatteryService on external stats like WiFi
+ mWorker.scheduleRunnable(() -> {
+ synchronized (mStats) {
+ final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status);
+ if (mStats.isOnBattery() == onBattery) {
+ // The battery state has not changed, so we don't need to sync external
+ // stats immediately.
+ mStats.setBatteryStateLocked(status, health, plugType, level, temp,
+ volt, chargeUAh, chargeFullUAh, chargeTimeToFullSeconds,
+ elapsedRealtime, uptime, currentTime);
+ return;
+ }
+ }
- // Sync external stats first as the battery has changed states. If we don't sync
- // before changing the state, we may not collect the relevant data later.
- // Order here is guaranteed since we're scheduling from the same thread and we are
- // using a single threaded executor.
- mWorker.scheduleSync("battery-state", BatteryExternalStatsWorker.UPDATE_ALL);
- mWorker.scheduleRunnable(() -> {
- synchronized (mStats) {
- mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
- chargeUAh, chargeFullUAh, chargeTimeToFullSeconds);
- }
+ // Sync external stats first as the battery has changed states. If we don't sync
+ // before changing the state, we may not collect the relevant data later.
+ // Order here is guaranteed since we're scheduling from the same thread and we
+ // are using a single threaded executor.
+ mWorker.scheduleSync("battery-state", BatteryExternalStatsWorker.UPDATE_ALL);
+ mWorker.scheduleRunnable(() -> {
+ synchronized (mStats) {
+ mStats.setBatteryStateLocked(status, health, plugType, level, temp,
+ volt, chargeUAh, chargeFullUAh, chargeTimeToFullSeconds,
+ elapsedRealtime, uptime, currentTime);
+ }
+ });
+ });
});
- });
+ }
}
public long getAwakeTimeBattery() {
@@ -1205,8 +1836,12 @@
try {
String reason;
while ((reason = waitWakeup()) != null) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
+
synchronized (mStats) {
- mStats.noteWakeupReasonLocked(reason);
+ mStats.noteWakeupReasonLocked(reason,
+ SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
}
}
} catch (RuntimeException e) {
@@ -1273,12 +1908,16 @@
}
private void dumpSettings(PrintWriter pw) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
mStats.dumpConstantsLocked(pw);
}
}
private void dumpCpuStats(PrintWriter pw) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
mStats.dumpCpuStatsLocked(pw);
}
@@ -1292,14 +1931,20 @@
return -1;
}
if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
mStats.setRecordAllHistoryLocked(enable);
}
} else if ("no-auto-reset".equals(args[i])) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
mStats.setNoAutoReset(enable);
}
} else if ("pretend-screen-off".equals(args[i])) {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
mStats.setPretendScreenOff(enable);
}
@@ -1350,6 +1995,7 @@
return;
}
final long events = ParseUtils.parseLong(args[i], 0);
+ awaitCompletion();
synchronized (mStats) {
mStats.createFakeHistoryEvents(events);
pw.println("Battery history create events started.");
@@ -1365,6 +2011,7 @@
} else if ("--daily".equals(arg)) {
flags |= BatteryStats.DUMP_DAILY_ONLY;
} else if ("--reset".equals(arg)) {
+ awaitCompletion();
synchronized (mStats) {
mStats.resetAllStatsCmdLocked();
pw.println("Battery stats reset.");
@@ -1372,6 +2019,7 @@
}
mWorker.scheduleSync("dump", BatteryExternalStatsWorker.UPDATE_ALL);
} else if ("--write".equals(arg)) {
+ awaitCompletion();
syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
synchronized (mStats) {
mStats.writeSyncLocked();
@@ -1379,12 +2027,14 @@
noOutput = true;
}
} else if ("--new-daily".equals(arg)) {
+ awaitCompletion();
synchronized (mStats) {
mStats.recordDailyStatsLocked();
pw.println("New daily stats written.");
noOutput = true;
}
} else if ("--read-daily".equals(arg)) {
+ awaitCompletion();
synchronized (mStats) {
mStats.readDailyStatsLocked();
pw.println("Last daily stats read.");
@@ -1441,6 +2091,7 @@
if (BatteryStatsHelper.checkWifiOnly(mContext)) {
flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
}
+ awaitCompletion();
// Fetch data from external sources and update the BatteryStatsImpl object with them.
syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
} finally {
@@ -1489,6 +2140,7 @@
}
}
if (DBG) Slog.d(TAG, "begin dumpProtoLocked from UID " + Binder.getCallingUid());
+ awaitCompletion();
synchronized (mStats) {
mStats.dumpProtoLocked(mContext, fd, apps, flags, historyStart);
if (writeData) {
@@ -1528,6 +2180,7 @@
}
}
if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
+ awaitCompletion();
synchronized (mStats) {
mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
if (writeData) {
@@ -1537,6 +2190,7 @@
if (DBG) Slog.d(TAG, "end dumpCheckinLocked");
} else {
if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
+ awaitCompletion();
synchronized (mStats) {
mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
if (writeData) {
@@ -1552,6 +2206,8 @@
* @hide
*/
public CellularBatteryStats getCellularBatteryStats() {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
return mStats.getCellularBatteryStats();
}
@@ -1562,6 +2218,8 @@
* @hide
*/
public WifiBatteryStats getWifiBatteryStats() {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
return mStats.getWifiBatteryStats();
}
@@ -1572,6 +2230,8 @@
* @hide
*/
public GpsBatteryStats getGpsBatteryStats() {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
synchronized (mStats) {
return mStats.getGpsBatteryStats();
}
@@ -1588,6 +2248,8 @@
}
long ident = Binder.clearCallingIdentity();
try {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
if (shouldCollectExternalStats()) {
syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
}
@@ -1614,6 +2276,8 @@
long ident = Binder.clearCallingIdentity();
int i=-1;
try {
+ // Wait for the completion of pending works if there is any
+ awaitCompletion();
if (shouldCollectExternalStats()) {
syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
}
@@ -1685,4 +2349,124 @@
Binder.restoreCallingIdentity(ident);
}
}
+
+ void updateForegroundTimeIfOnBattery(final String packageName, final int uid,
+ final long cpuTimeDiff) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ if (!isOnBattery()) {
+ return;
+ }
+ synchronized (mStats) {
+ final BatteryStatsImpl.Uid.Proc ps =
+ mStats.getProcessStatsLocked(uid, packageName, elapsedRealtime, uptime);
+ if (ps != null) {
+ ps.addForegroundTimeLocked(cpuTimeDiff);
+ }
+ }
+ });
+ }
+ }
+
+ void noteCurrentTimeChanged() {
+ synchronized (mLock) {
+ final long currentTime = System.currentTimeMillis();
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
+ }
+ });
+ }
+ }
+
+ void updateBatteryStatsOnActivityUsage(final String packageName, final String className,
+ final int uid, final int userId, final boolean resumed) {
+ synchronized (mLock) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
+ uid, packageName, className,
+ resumed
+ ? FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND
+ : FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND);
+ synchronized (mStats) {
+ if (resumed) {
+ mStats.noteActivityResumedLocked(uid, elapsedRealtime, uptime);
+ } else {
+ mStats.noteActivityPausedLocked(uid, elapsedRealtime, uptime);
+ }
+ }
+ });
+ }
+ }
+
+ void noteProcessDied(final int uid, final int pid) {
+ synchronized (mLock) {
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.noteProcessDiedLocked(uid, pid);
+ }
+ });
+ }
+ }
+
+ void reportExcessiveCpu(final int uid, final String processName, final long uptimeSince,
+ long cputimeUsed) {
+ synchronized (mLock) {
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.reportExcessiveCpuLocked(uid, processName, uptimeSince, cputimeUsed);
+ }
+ });
+ }
+ }
+
+ void noteServiceStartRunning(final BatteryStatsImpl.Uid.Pkg.Serv stats) {
+ synchronized (mLock) {
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ stats.startRunningLocked(uptime);
+ }
+ });
+ }
+ }
+
+ void noteServiceStopRunning(final BatteryStatsImpl.Uid.Pkg.Serv stats) {
+ synchronized (mLock) {
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ stats.stopRunningLocked(uptime);
+ }
+ });
+ }
+ }
+
+ void noteServiceStartLaunch(final BatteryStatsImpl.Uid.Pkg.Serv stats) {
+ synchronized (mLock) {
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ stats.startLaunchedLocked(uptime);
+ }
+ });
+ }
+ }
+
+ void noteServiceStopLaunch(final BatteryStatsImpl.Uid.Pkg.Serv stats) {
+ synchronized (mLock) {
+ final long uptime = SystemClock.uptimeMillis();
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ stats.stopLaunchedLocked(uptime);
+ }
+ });
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 6948f90..93105da 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -964,7 +964,7 @@
+ mParallelBroadcasts.size() + " parallel broadcasts; "
+ mDispatcher.describeStateLocked());
- mService.updateCpuStats();
+ mService.updateCpuStatsLocked();
if (fromMsg) {
mBroadcastsScheduled = false;
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index c5047e5..9660389 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -479,6 +479,21 @@
private static native void enableFreezerInternal(boolean enable);
/**
+ * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
+ * this method, this method will synchronously dispatch all pending transactions to the
+ * specified pid. This method will not add significant latencies when unfreezing.
+ * After freezing binder calls, binder will block all transaction to the frozen pid, and return
+ * an error to the sending process.
+ *
+ * @param pid the target pid for which binder transactions are to be frozen
+ * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze
+ * binder for the specificed pid.
+ *
+ * @throws RuntimeException in case a flush/freeze operation could not complete successfully.
+ */
+ private static native void freezeBinder(int pid, boolean freeze);
+
+ /**
* Determines whether the freezer is supported by this system
*/
public static boolean isFreezerSupported() {
@@ -727,6 +742,13 @@
}
if (!app.frozen) {
+ try {
+ freezeBinder(app.pid, false);
+ } catch (RuntimeException e) {
+ // TODO: it might be preferable to kill the target pid in this case
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName);
+ }
+
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName);
}
@@ -1039,6 +1061,14 @@
return;
}
+ try {
+ freezeBinder(pid, true);
+ } catch (RuntimeException e) {
+ // TODO: it might be preferable to kill the target pid in this case
+ Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
+ return;
+ }
+
if (pid == 0 || proc.frozen) {
// Already frozen or not a real process, either one being
// launched or one being killed
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index fc33031..c313eb5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -66,9 +66,9 @@
import static com.android.server.am.ActivityManagerService.TAG_LRU;
import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ;
import static com.android.server.am.ActivityManagerService.TAG_PROCESS_OBSERVERS;
-import static com.android.server.am.ActivityManagerService.TAG_PSS;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerService.TOP_APP_PRIORITY_BOOST;
+import static com.android.server.am.AppProfiler.TAG_PSS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import android.app.ActivityManager;
@@ -83,7 +83,6 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
-import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManagerInternal;
@@ -102,7 +101,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
@@ -819,7 +817,7 @@
}
if (allChanged) {
- mService.requestPssAllProcsLocked(now, false,
+ mService.mAppProfiler.requestPssAllProcsLocked(now, false,
mService.mProcessStats.isMemFactorLowered());
}
@@ -1075,7 +1073,7 @@
mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
- return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
+ return mService.mAppProfiler.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
}
private void updateAppUidRecLocked(ProcessRecord app) {
@@ -2176,7 +2174,7 @@
// normally be a B service, but if we are low on RAM and it
// is large we want to force it down since we would prefer to
// keep launcher over it.
- if (mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
+ if (!mService.mAppProfiler.isLastMemoryLevelNormal()
&& app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
app.serviceHighRam = true;
app.serviceb = true;
@@ -2493,45 +2491,16 @@
}
if (app.setProcState == PROCESS_STATE_NONEXISTENT
|| ProcessList.procStatesDifferForMem(app.getCurProcState(), app.setProcState)) {
- if (false && mService.mTestPssMode
- && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
- // Experimental code to more aggressively collect pss while
- // running test... the problem is that this tends to collect
- // the data right when a process is transitioning between process
- // states, which will tend to give noisy data.
- long start = SystemClock.uptimeMillis();
- long startTime = SystemClock.currentThreadTimeMillis();
- long pss = Debug.getPss(app.pid, mTmpLong, null);
- long endTime = SystemClock.currentThreadTimeMillis();
- mService.recordPssSampleLocked(app, app.getCurProcState(), pss,
- mTmpLong[0], mTmpLong[1], mTmpLong[2],
- ProcessStats.ADD_PSS_INTERNAL_SINGLE, endTime-startTime, now);
- mService.mPendingPssProcesses.remove(app);
- Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
- + " to " + app.getCurProcState() + ": "
- + (SystemClock.uptimeMillis()-start) + "ms");
- }
app.lastStateTime = now;
- app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(),
- app.procStateMemTracker, mService.mTestPssMode,
- mService.mAtmInternal.isSleeping(), now);
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
- + ProcessList.makeProcStateString(app.setProcState) + " to "
- + ProcessList.makeProcStateString(app.getCurProcState()) + " next pss in "
- + (app.nextPssTime-now) + ": " + app);
- } else {
- if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
- && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
- mService.mTestPssMode)))) {
- if (mService.requestPssLocked(app, app.setProcState)) {
- app.nextPssTime = ProcessList.computeNextPssTime(app.getCurProcState(),
- app.procStateMemTracker, mService.mTestPssMode,
- mService.mAtmInternal.isSleeping(), now);
- }
- } else if (false && DEBUG_PSS) {
- Slog.d(TAG_PSS,
- "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
+ mService.mAppProfiler.updateNextPssTimeLocked(app.getCurProcState(), app, now, true);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Process state change from "
+ + ProcessList.makeProcStateString(app.setProcState) + " to "
+ + ProcessList.makeProcStateString(app.getCurProcState()) + " next pss in "
+ + (app.nextPssTime - now) + ": " + app);
}
+ } else {
+ mService.mAppProfiler.updateNextPssTimeLocked(app.getCurProcState(), app, now, false);
}
if (app.setProcState != app.getCurProcState()) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 87898d8..ced2f0f 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -48,8 +48,8 @@
import static com.android.server.am.ActivityManagerService.TAG_LRU;
import static com.android.server.am.ActivityManagerService.TAG_NETWORK;
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 static com.android.server.am.AppProfiler.TAG_PSS;
import android.app.ActivityManager;
import android.app.ActivityThread;
@@ -1323,19 +1323,6 @@
return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE;
}
- public static void commitNextPssTime(ProcStateMemTracker tracker) {
- if (tracker.mPendingMemState >= 0) {
- tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
- tracker.mScalingFactor[tracker.mPendingMemState] = tracker.mPendingScalingFactor;
- tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
- tracker.mPendingMemState = -1;
- }
- }
-
- public static void abortNextPssTime(ProcStateMemTracker tracker) {
- tracker.mPendingMemState = -1;
- }
-
public static long computeNextPssTime(int procState, ProcStateMemTracker tracker, boolean test,
boolean sleeping, long now) {
boolean first;
@@ -1547,7 +1534,7 @@
ApplicationExitInfo.SUBREASON_LARGE_CACHED,
true);
} else if (proc != null && !keepIfLarge
- && mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
+ && !mService.mAppProfiler.isLastMemoryLevelNormal()
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc
.lastCachedPss);
@@ -1772,7 +1759,7 @@
mService.mProcessesOnHold.remove(app);
checkSlow(startTime, "startProcess: starting to update cpu stats");
- mService.updateCpuStats();
+ mService.updateCpuStatsLocked();
checkSlow(startTime, "startProcess: done updating cpu stats");
try {
@@ -2422,7 +2409,8 @@
ProcessList.killProcessGroup(app.uid, app.pid);
checkSlow(startTime, "startProcess: done killing old proc");
- if (!app.killed || mService.mLastMemoryLevel <= ProcessStats.ADJ_MEM_FACTOR_NORMAL
+ if (!app.killed
+ || mService.mAppProfiler.isLastMemoryLevelNormal()
|| app.setProcState < ActivityManager.PROCESS_STATE_CACHED_EMPTY
|| app.lastCachedPss < getCachedRestoreThresholdKb()) {
// Throw a wtf if it's not killed, or killed but not because the system was in
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 14bc6cb..f1e12c5 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1422,12 +1422,7 @@
@Override
public void clearProfilerIfNeeded() {
synchronized (mService) {
- if (mService.mProfileData.getProfileProc() == null
- || mService.mProfileData.getProfilerInfo() == null
- || mService.mProfileData.getProfileProc() != this) {
- return;
- }
- mService.clearProfilerLocked();
+ mService.mAppProfiler.clearProfilerLocked();
}
}
@@ -1483,7 +1478,7 @@
*/
@Override
public long getCpuTime() {
- return mService.mProcessCpuTracker.getCpuTimeForPid(pid);
+ return mService.mAppProfiler.getCpuTimeForPid(pid);
}
@Override
@@ -1492,7 +1487,7 @@
synchronized (mService) {
waitingToKill = null;
if (setProfileProc) {
- mService.mProfileData.setProfileProc(this);
+ mService.mAppProfiler.setProfileProcLocked(this);
}
if (packageName != null) {
addPackage(packageName, versionCode, mService.mProcessStats);
@@ -1566,7 +1561,7 @@
/** Non-private access is for tests only. */
@VisibleForTesting
boolean isMonitorCpuUsage() {
- return mService.MONITOR_CPU_USAGE;
+ return mService.mAppProfiler.MONITOR_CPU_USAGE;
}
void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
@@ -1701,9 +1696,7 @@
if (isMonitorCpuUsage()) {
mService.updateCpuStatsNow();
- synchronized (mService.mProcessCpuTracker) {
- report.append(mService.mProcessCpuTracker.printCurrentState(anrTime));
- }
+ mService.mAppProfiler.printCurrentCpuState(report, anrTime);
info.append(processCpuTracker.printCurrentLoad());
info.append(report);
}
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 4e8c386..d925def 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -314,7 +314,8 @@
private void scheduleRequestPssAllProcs(boolean always, boolean memLowered) {
mAm.mHandler.post(() -> {
synchronized (mAm) {
- mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), always, memLowered);
+ mAm.mAppProfiler.requestPssAllProcsLocked(
+ SystemClock.uptimeMillis(), always, memLowered);
}
});
}
@@ -1056,17 +1057,13 @@
}
}
} else if ("--start-testing".equals(arg)) {
- synchronized (mAm) {
- mAm.setTestPssMode(true);
- pw.println("Started high frequency sampling.");
- quit = true;
- }
+ mAm.mAppProfiler.setTestPssMode(true);
+ pw.println("Started high frequency sampling.");
+ quit = true;
} else if ("--stop-testing".equals(arg)) {
- synchronized (mAm) {
- mAm.setTestPssMode(false);
- pw.println("Stopped high frequency sampling.");
- quit = true;
- }
+ mAm.mAppProfiler.setTestPssMode(false);
+ pw.println("Stopped high frequency sampling.");
+ quit = true;
} else if ("--pretend-screen-on".equals(arg)) {
synchronized (mLock) {
mInjectedScreenState = true;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 5b12c8c..55e0f2e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -149,7 +149,7 @@
// allow the service becomes foreground service? Service started from background may not be
// allowed to become a foreground service.
- boolean mAllowStartForeground;
+ @ActiveServices.FgsFeatureRetCode int mAllowStartForeground;
String mInfoAllowStartForeground;
boolean mLoggedInfoAllowStartForeground;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index dfe8af1..b56b09d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2206,6 +2206,7 @@
updatePermissionRevokedCompat(uid, code, mode);
}
+ int previousMode;
synchronized (this) {
final int defaultMode = AppOpsManager.opToDefaultMode(code);
@@ -2214,12 +2215,14 @@
if (mode == defaultMode) {
return;
}
+ previousMode = AppOpsManager.MODE_DEFAULT;
uidState = new UidState(uid);
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
mUidStates.put(uid, uidState);
scheduleWriteLocked();
} else if (uidState.opModes == null) {
+ previousMode = AppOpsManager.MODE_DEFAULT;
if (mode != defaultMode) {
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
@@ -2229,6 +2232,7 @@
if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
return;
}
+ previousMode = uidState.opModes.get(code);
if (mode == defaultMode) {
uidState.opModes.delete(code);
if (uidState.opModes.size() <= 0) {
@@ -2243,7 +2247,7 @@
}
notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback);
- notifyOpChangedSync(code, uid, null, mode);
+ notifyOpChangedSync(code, uid, null, mode, previousMode);
}
/**
@@ -2420,11 +2424,12 @@
}
}
- private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
+ private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode,
+ int previousMode) {
final StorageManagerInternal storageManagerInternal =
LocalServices.getService(StorageManagerInternal.class);
if (storageManagerInternal != null) {
- storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode);
+ storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode, previousMode);
}
}
@@ -2458,11 +2463,13 @@
return;
}
+ int previousMode = AppOpsManager.MODE_DEFAULT;
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
Op op = getOpLocked(code, uid, packageName, null, bypass, true);
if (op != null) {
if (op.mode != mode) {
+ previousMode = op.mode;
op.mode = mode;
if (uidState != null) {
uidState.evalForegroundOps(mOpModeWatchers);
@@ -2499,7 +2506,7 @@
this, repCbs, code, uid, packageName));
}
- notifyOpChangedSync(code, uid, packageName, mode);
+ notifyOpChangedSync(code, uid, packageName, mode, previousMode);
}
private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
@@ -2542,7 +2549,7 @@
}
private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
- int op, int uid, String packageName) {
+ int op, int uid, String packageName, int previousMode) {
boolean duplicate = false;
if (reports == null) {
reports = new ArrayList<>();
@@ -2557,7 +2564,7 @@
}
}
if (!duplicate) {
- reports.add(new ChangeRec(op, uid, packageName));
+ reports.add(new ChangeRec(op, uid, packageName, previousMode));
}
return reports;
@@ -2565,7 +2572,7 @@
private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
- int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
+ int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) {
if (cbs == null) {
return callbacks;
}
@@ -2576,7 +2583,7 @@
for (int i=0; i<N; i++) {
ModeCallback cb = cbs.valueAt(i);
ArrayList<ChangeRec> reports = callbacks.get(cb);
- ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName);
+ ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode);
if (changed != reports) {
callbacks.put(cb, changed);
}
@@ -2588,11 +2595,13 @@
final int op;
final int uid;
final String pkg;
+ final int previous_mode;
- ChangeRec(int _op, int _uid, String _pkg) {
+ ChangeRec(int _op, int _uid, String _pkg, int _previous_mode) {
op = _op;
uid = _uid;
pkg = _pkg;
+ previous_mode = _previous_mode;
}
}
@@ -2628,18 +2637,19 @@
for (int j = uidOpCount - 1; j >= 0; j--) {
final int code = opModes.keyAt(j);
if (AppOpsManager.opAllowsReset(code)) {
+ int previousMode = opModes.valueAt(j);
opModes.removeAt(j);
if (opModes.size() <= 0) {
uidState.opModes = null;
}
for (String packageName : getPackagesForUid(uidState.uid)) {
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- mOpModeWatchers.get(code));
+ previousMode, mOpModeWatchers.get(code));
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- mPackageModeWatchers.get(packageName));
+ previousMode, mPackageModeWatchers.get(packageName));
allChanges = addChange(allChanges, code, uidState.uid,
- packageName);
+ packageName, previousMode);
}
}
}
@@ -2670,16 +2680,18 @@
Op curOp = pkgOps.valueAt(j);
if (AppOpsManager.opAllowsReset(curOp.op)
&& curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
+ int previousMode = curOp.mode;
curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
changed = true;
uidChanged = true;
final int uid = curOp.uidState.uid;
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- mOpModeWatchers.get(curOp.op));
+ previousMode, mOpModeWatchers.get(curOp.op));
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- mPackageModeWatchers.get(packageName));
+ previousMode, mPackageModeWatchers.get(packageName));
- allChanges = addChange(allChanges, curOp.op, uid, packageName);
+ allChanges = addChange(allChanges, curOp.op, uid, packageName,
+ previousMode);
curOp.removeAttributionsWithNoTime();
if (curOp.mAttributions.isEmpty()) {
pkgOps.removeAt(j);
@@ -2720,7 +2732,7 @@
for (int i = 0; i < numChanges; i++) {
ChangeRec change = allChanges.get(i);
notifyOpChangedSync(change.op, change.uid, change.pkg,
- AppOpsManager.opToDefaultMode(change.op));
+ AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
}
}
}
@@ -3926,7 +3938,7 @@
if (!isAttributionTagValid) {
String msg = "attributionTag " + attributionTag + " not declared in"
- + "manifest of " + packageName;
+ + " manifest of " + packageName;
try {
if (mPlatformCompat.isChangeEnabledByPackageName(
SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index d2c35fe..1613d3b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -282,8 +282,10 @@
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
final boolean supportsSelfIllumination = context.getResources()
.getBoolean(R.bool.config_faceAuthSupportsSelfIllumination);
+ final int maxTemplatesAllowed = context.getResources()
+ .getInteger(R.integer.config_faceMaxTemplatesPerUser);
mFaceSensorProperties = new FaceSensorProperties(sensorId, false /* supportsFaceDetect */,
- supportsSelfIllumination);
+ supportsSelfIllumination, maxTemplatesAllowed);
mContext = context;
mSensorId = sensorId;
mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
index 3754bd7..7e62329 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
@@ -45,6 +45,7 @@
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
+import com.android.internal.R;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto;
@@ -338,8 +339,10 @@
: FingerprintSensorProperties.TYPE_REAR;
// resetLockout is controlled by the framework, so hardwareAuthToken is not required
final boolean resetLockoutRequiresHardwareAuthToken = false;
+ final int maxTemplatesAllowed = mContext.getResources()
+ .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
mSensorProperties = new FingerprintSensorProperties(sensorId, sensorType,
- resetLockoutRequiresHardwareAuthToken);
+ resetLockoutRequiresHardwareAuthToken, maxTemplatesAllowed);
}
static Fingerprint21 newInstance(@NonNull Context context, int sensorId,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java
index 1a6ad46..7cab2b8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21UdfpsMock.java
@@ -35,6 +35,7 @@
import android.util.Slog;
import android.util.SparseBooleanArray;
+import com.android.internal.R;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.ClientMonitor;
@@ -408,8 +409,11 @@
mHandler = handler;
// resetLockout is controlled by the framework, so hardwareAuthToken is not required
final boolean resetLockoutRequiresHardwareAuthToken = false;
+ final int maxTemplatesAllowed = mContext.getResources()
+ .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
mSensorProperties = new FingerprintSensorProperties(sensorId,
- FingerprintSensorProperties.TYPE_UDFPS, resetLockoutRequiresHardwareAuthToken);
+ FingerprintSensorProperties.TYPE_UDFPS, resetLockoutRequiresHardwareAuthToken,
+ maxTemplatesAllowed);
mMockHalResultController = controller;
mUserHasTrust = new SparseBooleanArray();
mTrustManager = context.getSystemService(TrustManager.class);
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 92fce8a..c7de8d3 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -107,17 +107,23 @@
}
/**
- * Internal version of the above method. Does not perform costly permission check.
+ * Internal version of the above method, without logging. Does not perform costly permission
+ * check.
+ * TODO(b/167551701): Remove this method and add 'loggability' as a changeid property.
+ */
+ public boolean isChangeEnabledInternalNoLogging(long changeId, ApplicationInfo appInfo) {
+ return mCompatConfig.isChangeEnabled(changeId, appInfo);
+ }
+
+ /**
+ * Internal version of {@link #isChangeEnabled(long, ApplicationInfo)}. Does not perform costly
+ * permission check.
*/
public boolean isChangeEnabledInternal(long changeId, ApplicationInfo appInfo) {
- if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
- reportChange(changeId, appInfo.uid,
- ChangeReporter.STATE_ENABLED);
- return true;
- }
+ boolean value = isChangeEnabledInternalNoLogging(changeId, appInfo);
reportChange(changeId, appInfo.uid,
- ChangeReporter.STATE_DISABLED);
- return false;
+ value ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
+ return value;
}
@Override
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 36d69c9..f42e18a 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -17,8 +17,8 @@
package com.android.server.display;
import android.annotation.Nullable;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
@@ -846,7 +846,7 @@
public void run() {
try {
// The foreground app is the top activity of the focused tasks stack.
- final StackInfo info = mActivityTaskManager.getFocusedStackInfo();
+ final RootTaskInfo info = mActivityTaskManager.getFocusedRootTaskInfo();
if (info == null || info.topActivity == null) {
return;
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index eea1980..9e82d4f 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -20,6 +20,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -377,14 +378,14 @@
}
try {
- final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack();
- if (focusedStack != null && focusedStack.topActivity != null) {
- builder.setUserId(focusedStack.userId);
- builder.setPackageName(focusedStack.topActivity.getPackageName());
+ final RootTaskInfo focusedTask = mInjector.getFocusedStack();
+ if (focusedTask != null && focusedTask.topActivity != null) {
+ builder.setUserId(focusedTask.userId);
+ builder.setPackageName(focusedTask.topActivity.getPackageName());
} else {
// Ignore the event because we can't determine user / package.
if (DEBUG) {
- Slog.d(TAG, "Ignoring event due to null focusedStack.");
+ Slog.d(TAG, "Ignoring event due to null focusedTask.");
}
return;
}
@@ -1104,8 +1105,8 @@
}
}
- public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
- return ActivityTaskManager.getService().getFocusedStackInfo();
+ public RootTaskInfo getFocusedStack() throws RemoteException {
+ return ActivityTaskManager.getService().getFocusedRootTaskInfo();
}
public void scheduleIdleJob(Context context) {
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 3c05080..cc6687f 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -869,10 +869,11 @@
}
private void updateRefreshRateSettingLocked() {
- float minRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
- Settings.System.MIN_REFRESH_RATE, 0f);
- float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
- Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
+ final ContentResolver cr = mContext.getContentResolver();
+ float minRefreshRate = Settings.System.getFloatForUser(cr,
+ Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId());
+ float peakRefreshRate = Settings.System.getFloatForUser(cr,
+ Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId());
updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate);
}
@@ -1301,8 +1302,9 @@
}
// TODO: brightnessfloat: make it use float not int
private void onBrightnessChangedLocked() {
- int brightness = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, -1);
+ final ContentResolver cr = mContext.getContentResolver();
+ int brightness = Settings.System.getIntForUser(cr,
+ Settings.System.SCREEN_BRIGHTNESS, -1, cr.getUserId());
Vote vote = null;
boolean insideZone = isInsideZone(brightness, mAmbientLux);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 813def4..6c14b2c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -222,7 +222,7 @@
private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel);
private static native void nativeRegisterInputMonitor(long ptr, InputChannel inputChannel,
int displayId, boolean isGestureMonitor);
- private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
+ private static native void nativeUnregisterInputChannel(long ptr, IBinder connectionToken);
private static native void nativePilferPointers(long ptr, IBinder token);
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
private static native void nativeSetInTouchMode(long ptr, boolean inTouchMode);
@@ -581,17 +581,17 @@
/**
* Unregisters an input channel.
- * @param inputChannel The input channel to unregister.
+ * @param connectionToken The input channel to unregister.
*/
- public void unregisterInputChannel(InputChannel inputChannel) {
- if (inputChannel == null) {
- throw new IllegalArgumentException("inputChannel must not be null.");
+ public void unregisterInputChannel(IBinder connectionToken) {
+ if (connectionToken == null) {
+ throw new IllegalArgumentException("connectionToken must not be null.");
}
synchronized (mGestureMonitorPidsLock) {
- mGestureMonitorPidsByToken.remove(inputChannel.getToken());
+ mGestureMonitorPidsByToken.remove(connectionToken);
}
- nativeUnregisterInputChannel(mPtr, inputChannel);
+ nativeUnregisterInputChannel(mPtr, connectionToken);
}
/**
@@ -2455,7 +2455,7 @@
@Override
public void dispose() {
- nativeUnregisterInputChannel(mPtr, mInputChannel);
+ nativeUnregisterInputChannel(mPtr, mInputChannel.getToken());
mInputChannel.dispose();
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5bc6e23..7401403 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1684,8 +1684,10 @@
final IntArray userIds = mUserProfiles.getCurrentProfileIds();
for (int i = 0; i < userIds.size(); i++) {
- mArchive.updateHistoryEnabled(userIds.get(i), Settings.Secure.getInt(resolver,
- Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0) == 1);
+ mArchive.updateHistoryEnabled(userIds.get(i),
+ Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0,
+ userIds.get(i)) == 1);
}
}
if (uri == null || NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI.equals(uri)) {
@@ -1956,6 +1958,13 @@
}
@Override
+ void onConsolidatedPolicyChanged() {
+ Binder.withCleanCallingIdentity(() -> {
+ mRankingHandler.requestSort();
+ });
+ }
+
+ @Override
void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {
Binder.withCleanCallingIdentity(() -> {
Intent intent = new Intent(ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED);
@@ -7148,9 +7157,10 @@
}
protected void playInCallNotification() {
+ final ContentResolver cr = getContext().getContentResolver();
if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_NORMAL
- && Settings.Secure.getInt(getContext().getContentResolver(),
- Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, 1) != 0) {
+ && Settings.Secure.getIntForUser(cr,
+ Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, 1, cr.getUserId()) != 0) {
new Thread() {
@Override
public void run() {
@@ -8462,7 +8472,10 @@
if (Notification.CATEGORY_CAR_EMERGENCY.equals(notification.category)
|| Notification.CATEGORY_CAR_WARNING.equals(notification.category)
|| Notification.CATEGORY_CAR_INFORMATION.equals(notification.category)) {
- checkCallerIsSystem();
+ getContext().enforceCallingPermission(
+ android.Manifest.permission.SEND_CATEGORY_CAR_NOTIFICATIONS,
+ String.format("Notification category %s restricted",
+ notification.category));
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index bae02ac..cff4f07 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -469,6 +469,69 @@
pw.println(prefix + "key=" + getSbn().getKey());
pw.println(prefix + "seen=" + mStats.hasSeen());
pw.println(prefix + "groupKey=" + getGroupKey());
+ pw.println(prefix + "notification=");
+ dumpNotification(pw, prefix + prefix, notification, redact);
+ pw.println(prefix + "publicNotification=");
+ dumpNotification(pw, prefix + prefix, notification.publicVersion, redact);
+ pw.println(prefix + "stats=" + stats.toString());
+ pw.println(prefix + "mContactAffinity=" + mContactAffinity);
+ pw.println(prefix + "mRecentlyIntrusive=" + mRecentlyIntrusive);
+ pw.println(prefix + "mPackagePriority=" + mPackagePriority);
+ pw.println(prefix + "mPackageVisibility=" + mPackageVisibility);
+ pw.println(prefix + "mSystemImportance="
+ + NotificationListenerService.Ranking.importanceToString(mSystemImportance));
+ pw.println(prefix + "mAsstImportance="
+ + NotificationListenerService.Ranking.importanceToString(mAssistantImportance));
+ pw.println(prefix + "mImportance="
+ + NotificationListenerService.Ranking.importanceToString(mImportance));
+ pw.println(prefix + "mImportanceExplanation=" + getImportanceExplanation());
+ pw.println(prefix + "mIsAppImportanceLocked=" + mIsAppImportanceLocked);
+ pw.println(prefix + "mIntercept=" + mIntercept);
+ pw.println(prefix + "mHidden==" + mHidden);
+ pw.println(prefix + "mGlobalSortKey=" + mGlobalSortKey);
+ pw.println(prefix + "mRankingTimeMs=" + mRankingTimeMs);
+ pw.println(prefix + "mCreationTimeMs=" + mCreationTimeMs);
+ pw.println(prefix + "mVisibleSinceMs=" + mVisibleSinceMs);
+ pw.println(prefix + "mUpdateTimeMs=" + mUpdateTimeMs);
+ pw.println(prefix + "mInterruptionTimeMs=" + mInterruptionTimeMs);
+ pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
+ if (mPreChannelsNotification) {
+ pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
+ notification.defaults, notification.flags));
+ pw.println(prefix + "n.sound=" + notification.sound);
+ pw.println(prefix + "n.audioStreamType=" + notification.audioStreamType);
+ pw.println(prefix + "n.audioAttributes=" + notification.audioAttributes);
+ pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d",
+ notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
+ pw.println(prefix + "vibrate=" + Arrays.toString(notification.vibrate));
+ }
+ pw.println(prefix + "mSound= " + mSound);
+ pw.println(prefix + "mVibration= " + mVibration);
+ pw.println(prefix + "mAttributes= " + mAttributes);
+ pw.println(prefix + "mLight= " + mLight);
+ pw.println(prefix + "mShowBadge=" + mShowBadge);
+ pw.println(prefix + "mColorized=" + notification.isColorized());
+ pw.println(prefix + "mAllowBubble=" + mAllowBubble);
+ pw.println(prefix + "isBubble=" + notification.isBubbleNotification());
+ pw.println(prefix + "mIsInterruptive=" + mIsInterruptive);
+ pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
+ if (getPeopleOverride() != null) {
+ pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
+ }
+ if (getSnoozeCriteria() != null) {
+ pw.println(prefix + "snoozeCriteria=" + TextUtils.join(",", getSnoozeCriteria()));
+ }
+ pw.println(prefix + "mAdjustments=" + mAdjustments);
+ pw.println(prefix + "shortcut=" + notification.getShortcutId()
+ + " found valid? " + (mShortcutInfo != null));
+ }
+
+ private void dumpNotification(PrintWriter pw, String prefix, Notification notification,
+ boolean redact) {
+ if (notification == null) {
+ pw.println(prefix + "None");
+ return;
+ }
pw.println(prefix + "fullscreenIntent=" + notification.fullScreenIntent);
pw.println(prefix + "contentIntent=" + notification.contentIntent);
pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
@@ -545,57 +608,6 @@
}
pw.println(prefix + "}");
}
- pw.println(prefix + "stats=" + stats.toString());
- pw.println(prefix + "mContactAffinity=" + mContactAffinity);
- pw.println(prefix + "mRecentlyIntrusive=" + mRecentlyIntrusive);
- pw.println(prefix + "mPackagePriority=" + mPackagePriority);
- pw.println(prefix + "mPackageVisibility=" + mPackageVisibility);
- pw.println(prefix + "mSystemImportance="
- + NotificationListenerService.Ranking.importanceToString(mSystemImportance));
- pw.println(prefix + "mAsstImportance="
- + NotificationListenerService.Ranking.importanceToString(mAssistantImportance));
- pw.println(prefix + "mImportance="
- + NotificationListenerService.Ranking.importanceToString(mImportance));
- pw.println(prefix + "mImportanceExplanation=" + getImportanceExplanation());
- pw.println(prefix + "mIsAppImportanceLocked=" + mIsAppImportanceLocked);
- pw.println(prefix + "mIntercept=" + mIntercept);
- pw.println(prefix + "mHidden==" + mHidden);
- pw.println(prefix + "mGlobalSortKey=" + mGlobalSortKey);
- pw.println(prefix + "mRankingTimeMs=" + mRankingTimeMs);
- pw.println(prefix + "mCreationTimeMs=" + mCreationTimeMs);
- pw.println(prefix + "mVisibleSinceMs=" + mVisibleSinceMs);
- pw.println(prefix + "mUpdateTimeMs=" + mUpdateTimeMs);
- pw.println(prefix + "mInterruptionTimeMs=" + mInterruptionTimeMs);
- pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
- if (mPreChannelsNotification) {
- pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
- notification.defaults, notification.flags));
- pw.println(prefix + "n.sound=" + notification.sound);
- pw.println(prefix + "n.audioStreamType=" + notification.audioStreamType);
- pw.println(prefix + "n.audioAttributes=" + notification.audioAttributes);
- pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d",
- notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
- pw.println(prefix + "vibrate=" + Arrays.toString(notification.vibrate));
- }
- pw.println(prefix + "mSound= " + mSound);
- pw.println(prefix + "mVibration= " + mVibration);
- pw.println(prefix + "mAttributes= " + mAttributes);
- pw.println(prefix + "mLight= " + mLight);
- pw.println(prefix + "mShowBadge=" + mShowBadge);
- pw.println(prefix + "mColorized=" + notification.isColorized());
- pw.println(prefix + "mAllowBubble=" + mAllowBubble);
- pw.println(prefix + "isBubble=" + notification.isBubbleNotification());
- pw.println(prefix + "mIsInterruptive=" + mIsInterruptive);
- pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
- if (getPeopleOverride() != null) {
- pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
- }
- if (getSnoozeCriteria() != null) {
- pw.println(prefix + "snoozeCriteria=" + TextUtils.join(",", getSnoozeCriteria()));
- }
- pw.println(prefix + "mAdjustments=" + mAdjustments);
- pw.println(prefix + "shortcut=" + notification.getShortcutId()
- + " found valid? " + (mShortcutInfo != null));
}
@Override
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 5417275..13cd6e5 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -417,7 +417,9 @@
if (mConfig == null) return;
newConfig = mConfig.copy();
- setAutomaticZenRuleStateLocked(newConfig, newConfig.automaticRules.get(id), condition);
+ ArrayList<ZenRule> rules = new ArrayList<>();
+ rules.add(newConfig.automaticRules.get(id));
+ setAutomaticZenRuleStateLocked(newConfig, rules, condition);
}
}
@@ -428,31 +430,34 @@
newConfig = mConfig.copy();
setAutomaticZenRuleStateLocked(newConfig,
- findMatchingRule(newConfig, ruleDefinition, condition),
+ findMatchingRules(newConfig, ruleDefinition, condition),
condition);
}
}
- private void setAutomaticZenRuleStateLocked(ZenModeConfig config, ZenRule rule,
+ private void setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules,
Condition condition) {
- if (rule == null) return;
+ if (rules == null || rules.isEmpty()) return;
- rule.condition = condition;
- updateSnoozing(rule);
- setConfigLocked(config, rule.component, "conditionChanged");
+ for (ZenRule rule : rules) {
+ rule.condition = condition;
+ updateSnoozing(rule);
+ setConfigLocked(config, rule.component, "conditionChanged");
+ }
}
- private ZenRule findMatchingRule(ZenModeConfig config, Uri id, Condition condition) {
+ private List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id, Condition condition) {
+ List<ZenRule> matchingRules= new ArrayList<>();
if (ruleMatches(id, condition, config.manualRule)) {
- return config.manualRule;
+ matchingRules.add(config.manualRule);
} else {
for (ZenRule automaticRule : config.automaticRules.values()) {
if (ruleMatches(id, condition, automaticRule)) {
- return automaticRule;
+ matchingRules.add(automaticRule);
}
}
}
- return null;
+ return matchingRules;
}
private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index 8c03c6c..8121a43e9 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -26,6 +26,7 @@
import android.text.TextUtils;
import android.util.Pair;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -66,7 +67,7 @@
String actorNamespace = actorUri.getAuthority();
Map<String, String> namespace = namedActors.get(actorNamespace);
- if (namespace == null) {
+ if (ArrayUtils.isEmpty(namespace)) {
return Pair.create(null, ActorState.MISSING_NAMESPACE);
}
@@ -102,21 +103,32 @@
* See {@link OverlayActorEnforcer} class comment for actor requirements.
* @return true if the actor is allowed to act on the target overlayInfo
*/
- private ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo,
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo,
int callingUid, int userId) {
+ // Checked first to avoid package not found errors, which are ignored for calls from shell
switch (callingUid) {
case Process.ROOT_UID:
case Process.SYSTEM_UID:
return ActorState.ALLOWED;
}
+ final String targetPackageName = overlayInfo.targetPackageName;
+ final PackageInfo targetPkgInfo = mPackageManager.getPackageInfo(targetPackageName, userId);
+ if (targetPkgInfo == null) {
+ return ActorState.TARGET_NOT_FOUND;
+ }
+
+ if ((targetPkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ return ActorState.ALLOWED;
+ }
+
String[] callingPackageNames = mPackageManager.getPackagesForUid(callingUid);
if (ArrayUtils.isEmpty(callingPackageNames)) {
return ActorState.NO_PACKAGES_FOR_UID;
}
// A target is always an allowed actor for itself
- String targetPackageName = overlayInfo.targetPackageName;
if (ArrayUtils.contains(callingPackageNames, targetPackageName)) {
return ActorState.ALLOWED;
}
@@ -149,7 +161,7 @@
targetOverlayable = mPackageManager.getOverlayableForTarget(targetPackageName,
targetOverlayableName, userId);
} catch (IOException e) {
- return ActorState.UNABLE_TO_GET_TARGET;
+ return ActorState.UNABLE_TO_GET_TARGET_OVERLAYABLE;
}
if (targetOverlayable == null) {
@@ -189,7 +201,7 @@
}
// Currently only pre-installed apps can be actors
- if (!appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) {
+ if (!appInfo.isSystemApp()) {
return ActorState.ACTOR_NOT_PREINSTALLED;
}
@@ -203,22 +215,25 @@
/**
* For easier logging/debugging, a set of all possible failure/success states when running
* enforcement.
+ *
+ * The ordering of this enum should be maintained in the order that cases are checked in code,
+ * as this ordering is used inside OverlayActorEnforcerTests.
*/
public enum ActorState {
- ALLOWED,
- INVALID_ACTOR,
- MISSING_NAMESPACE,
- MISSING_PACKAGE,
- MISSING_APP_INFO,
- ACTOR_NOT_PREINSTALLED,
+ TARGET_NOT_FOUND,
NO_PACKAGES_FOR_UID,
- MISSING_ACTOR_NAME,
- ERROR_READING_OVERLAYABLE,
MISSING_TARGET_OVERLAYABLE_NAME,
+ MISSING_LEGACY_PERMISSION,
+ ERROR_READING_OVERLAYABLE,
+ UNABLE_TO_GET_TARGET_OVERLAYABLE,
MISSING_OVERLAYABLE,
INVALID_OVERLAYABLE_ACTOR_NAME,
NO_NAMED_ACTORS,
- UNABLE_TO_GET_TARGET,
- MISSING_LEGACY_PERMISSION
+ MISSING_NAMESPACE,
+ MISSING_ACTOR_NAME,
+ MISSING_APP_INFO,
+ ACTOR_NOT_PREINSTALLED,
+ INVALID_ACTOR,
+ ALLOWED
}
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 07527c2..5b5ec42 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -778,7 +778,7 @@
void registerApkInApex(AndroidPackage pkg) {
synchronized (mLock) {
for (ActiveApexInfo aai : mActiveApexInfosCache) {
- if (pkg.getBaseCodePath().startsWith(aai.apexDirectory.getAbsolutePath())) {
+ if (pkg.getBaseApkPath().startsWith(aai.apexDirectory.getAbsolutePath())) {
List<String> apks = mApksInApex.get(aai.apexModuleName);
if (apks == null) {
apks = Lists.newArrayList();
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index f168ac7..dac2e4f 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -303,7 +303,8 @@
private void updateEnabledState(@NonNull AndroidPackage pkg) {
// TODO(b/135203078): Do not use toAppInfo
- final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternal(
+ // TODO(b/167551701): Make changeId non-logging
+ final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternalNoLogging(
PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
if (enabled) {
mDisabledPackages.remove(pkg.getPackageName());
@@ -639,24 +640,74 @@
}
}
- private void updateEntireShouldFilterCacheAsync() {
- mBackgroundExecutor.execute(this::updateEntireShouldFilterCache);
- }
-
private void updateEntireShouldFilterCache() {
mStateProvider.runWithState((settings, users) -> {
SparseArray<SparseBooleanArray> cache =
- new SparseArray<>(users.length * settings.size());
- for (int i = settings.size() - 1; i >= 0; i--) {
- updateShouldFilterCacheForPackage(cache,
- null /*skipPackage*/, settings.valueAt(i), settings, users, i);
- }
+ updateEntireShouldFilterCacheInner(settings, users);
synchronized (mCacheLock) {
mShouldFilterCache = cache;
}
});
}
+ private SparseArray<SparseBooleanArray> updateEntireShouldFilterCacheInner(
+ ArrayMap<String, PackageSetting> settings, UserInfo[] users) {
+ SparseArray<SparseBooleanArray> cache =
+ new SparseArray<>(users.length * settings.size());
+ for (int i = settings.size() - 1; i >= 0; i--) {
+ updateShouldFilterCacheForPackage(cache,
+ null /*skipPackage*/, settings.valueAt(i), settings, users, i);
+ }
+ return cache;
+ }
+
+ private void updateEntireShouldFilterCacheAsync() {
+ mBackgroundExecutor.execute(() -> {
+ final ArrayMap<String, PackageSetting> settingsCopy = new ArrayMap<>();
+ final ArrayMap<String, AndroidPackage> packagesCache = new ArrayMap<>();
+ final UserInfo[][] usersRef = new UserInfo[1][];
+ mStateProvider.runWithState((settings, users) -> {
+ packagesCache.ensureCapacity(settings.size());
+ settingsCopy.putAll(settings);
+ usersRef[0] = users;
+ // store away the references to the immutable packages, since settings are retained
+ // during updates.
+ for (int i = 0, max = settings.size(); i < max; i++) {
+ final AndroidPackage pkg = settings.valueAt(i).pkg;
+ packagesCache.put(settings.keyAt(i), pkg);
+ }
+ });
+ SparseArray<SparseBooleanArray> cache =
+ updateEntireShouldFilterCacheInner(settingsCopy, usersRef[0]);
+ boolean[] changed = new boolean[1];
+ // We have a cache, let's make sure the world hasn't changed out from under us.
+ mStateProvider.runWithState((settings, users) -> {
+ if (settings.size() != settingsCopy.size()) {
+ changed[0] = true;
+ return;
+ }
+ for (int i = 0, max = settings.size(); i < max; i++) {
+ final AndroidPackage pkg = settings.valueAt(i).pkg;
+ if (!Objects.equals(pkg, packagesCache.get(settings.keyAt(i)))) {
+ changed[0] = true;
+ return;
+ }
+ }
+ });
+ if (changed[0]) {
+ // Something has changed, just update the cache inline with the lock held
+ updateEntireShouldFilterCache();
+ if (DEBUG_LOGGING) {
+ Slog.i(TAG, "Rebuilding cache with lock due to package change.");
+ }
+ } else {
+ synchronized (mCacheLock) {
+ mShouldFilterCache = cache;
+ }
+ }
+ });
+ }
+
public void onUsersChanged() {
synchronized (mCacheLock) {
if (mShouldFilterCache != null) {
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index d25ddad..4be509b 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -623,7 +623,6 @@
AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
if (pkg != null) {
- // TODO(b/135203078): Print AppInfo?
pw.print(" applicationInfo="); pw.println(pkg.toAppInfoWithoutState());
}
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index eddab76..7db2319 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -384,17 +384,17 @@
if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
continue;
}
- if (pkg.getCodePath() == null) {
+ if (pkg.getPath() == null) {
Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
continue;
}
// If the path is in /system, /vendor, /product or /system_ext, ignore. It will
// have been ota-dexopted into /data/ota and moved into the dalvik-cache already.
- if (pkg.getCodePath().startsWith("/system")
- || pkg.getCodePath().startsWith("/vendor")
- || pkg.getCodePath().startsWith("/product")
- || pkg.getCodePath().startsWith("/system_ext")) {
+ if (pkg.getPath().startsWith("/system")
+ || pkg.getPath().startsWith("/vendor")
+ || pkg.getPath().startsWith("/product")
+ || pkg.getPath().startsWith("/system_ext")) {
continue;
}
@@ -408,7 +408,7 @@
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (String path : paths) {
String oatDir = PackageDexOptimizer.getOatDir(
- new File(pkg.getCodePath())).getAbsolutePath();
+ new File(pkg.getPath())).getAbsolutePath();
// TODO: Check first whether there is an artifact, to save the roundtrip time.
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 8af7e1f..da4ea16 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -136,7 +136,7 @@
// Trying to derive the paths, thus need the raw ABI info from the parsed package, and the
// current state in PackageSetting is irrelevant.
return deriveNativeLibraryPaths(new Abis(pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi()),
- appLib32InstallDir, pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(),
+ appLib32InstallDir, pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(),
isUpdatedSystemApp);
}
@@ -205,11 +205,11 @@
@Override
public Abis getBundledAppAbis(AndroidPackage pkg) {
- final String apkName = deriveCodePathName(pkg.getCodePath());
+ final String apkName = deriveCodePathName(pkg.getPath());
// If "/system/lib64/apkname" exists, assume that is the per-package
// native library directory to use; otherwise use "/system/lib/apkname".
- final String apkRoot = calculateBundledApkRoot(pkg.getBaseCodePath());
+ final String apkRoot = calculateBundledApkRoot(pkg.getBaseApkPath());
final Abis abis = getBundledAppAbi(pkg, apkRoot, apkName);
return abis;
}
@@ -223,7 +223,7 @@
* @param apkName the name of the installed package.
*/
private Abis getBundledAppAbi(AndroidPackage pkg, String apkRoot, String apkName) {
- final File codeFile = new File(pkg.getCodePath());
+ final File codeFile = new File(pkg.getPath());
final boolean has64BitLibs;
final boolean has32BitLibs;
@@ -304,15 +304,15 @@
String pkgRawSecondaryCpuAbi = AndroidPackageUtils.getRawSecondaryCpuAbi(pkg);
final NativeLibraryPaths initialLibraryPaths = deriveNativeLibraryPaths(
new Abis(pkgRawPrimaryCpuAbi, pkgRawSecondaryCpuAbi),
- PackageManagerService.sAppLib32InstallDir, pkg.getCodePath(),
- pkg.getBaseCodePath(), pkg.isSystem(),
+ PackageManagerService.sAppLib32InstallDir, pkg.getPath(),
+ pkg.getBaseApkPath(), pkg.isSystem(),
isUpdatedSystemApp);
final boolean extractLibs = shouldExtractLibs(pkg, isUpdatedSystemApp);
final String nativeLibraryRootStr = initialLibraryPaths.nativeLibraryRootDir;
final boolean useIsaSpecificSubdirs = initialLibraryPaths.nativeLibraryRootRequiresIsa;
- final boolean onIncremental = isIncrementalPath(pkg.getCodePath());
+ final boolean onIncremental = isIncrementalPath(pkg.getPath());
String primaryCpuAbi = null;
String secondaryCpuAbi = null;
@@ -453,7 +453,7 @@
final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi);
return new Pair<>(abis,
deriveNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir,
- pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(),
+ pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(),
isUpdatedSystemApp));
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 0d8ba3e..42e6d8f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -199,7 +199,7 @@
throw new IllegalStateException("Inconsistent information "
+ "between PackageParser.Package and its ApplicationInfo. "
+ "pkg.getAllCodePaths=" + paths
- + " pkg.getBaseCodePath=" + pkg.getBaseCodePath()
+ + " pkg.getBaseCodePath=" + pkg.getBaseApkPath()
+ " pkg.getSplitCodePaths="
+ (splitCodePaths == null ? "null" : Arrays.toString(splitCodePaths)));
}
@@ -772,7 +772,7 @@
if (!AndroidPackageUtils.canHaveOatDir(pkg, isUpdatedSystemApp)) {
return null;
}
- File codePath = new File(pkg.getCodePath());
+ File codePath = new File(pkg.getPath());
if (!codePath.isDirectory()) {
return null;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ca12532..17cd8f5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2083,7 +2083,7 @@
if (ps == null) {
return 0;
}
- final File apkDirOrPath = ps.getCodePath();
+ final File apkDirOrPath = ps.getPath();
if (apkDirOrPath == null) {
return 0;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 89e0393..fcf5d96 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2220,7 +2220,7 @@
// Send installed broadcasts if the package is not a static shared lib.
if (res.pkg.getStaticSharedLibName() == null) {
mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(
- res.pkg.getBaseCodePath());
+ res.pkg.getBaseApkPath());
// Send added for users that see the package for the first time
// sendPackageAddedForNewUsers also deals with system apps
@@ -3101,7 +3101,7 @@
final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i);
- if (!isExternal(ps) && (ps.getCodePath() == null || !ps.getCodePath().exists())
+ if (!isExternal(ps) && (ps.getPath() == null || !ps.getPath().exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
mSettings.mPackages.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
@@ -3266,11 +3266,11 @@
logCriticalInfo(Log.WARN,
"Expecting better updated system app for " + ps.name
+ "; removing system app. Last known"
- + " codePath=" + ps.getCodePathString()
+ + " codePath=" + ps.getPathString()
+ ", versionCode=" + ps.versionCode
+ "; scanned versionCode=" + scannedPkg.getLongVersionCode());
removePackageLI(scannedPkg, true);
- mExpectingBetter.put(ps.name, ps.getCodePath());
+ mExpectingBetter.put(ps.name, ps.getPath());
}
continue;
@@ -3293,14 +3293,14 @@
// code path, but, changes the package name.
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
- if (disabledPs.getCodePath() == null || !disabledPs.getCodePath().exists()
+ if (disabledPs.getPath() == null || !disabledPs.getPath().exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
} else {
// We're expecting that the system app should remain disabled, but add
// it to expecting better to recover in case the data version cannot
// be scanned.
- mExpectingBetter.put(disabledPs.name, disabledPs.getCodePath());
+ mExpectingBetter.put(disabledPs.name, disabledPs.getPath());
}
}
}
@@ -3373,7 +3373,7 @@
// special privileges
removePackageLI(pkg, true);
try {
- final File codePath = new File(pkg.getCodePath());
+ final File codePath = new File(pkg.getPath());
scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse updated, ex-system package: "
@@ -3854,7 +3854,7 @@
// If we don't, installing the system package fails during scan
enableSystemPackageLPw(stubPkg);
}
- installPackageFromSystemLIF(stubPkg.getCodePath(),
+ installPackageFromSystemLIF(stubPkg.getPath(),
mUserManager.getUserIds() /*allUserHandles*/, null /*origUserHandles*/,
true /*writeSettings*/);
} catch (PackageManagerException pme) {
@@ -3878,7 +3878,7 @@
clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
mDexManager.notifyPackageUpdated(pkg.getPackageName(),
- pkg.getBaseCodePath(), pkg.getSplitCodePaths());
+ pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
return true;
}
@@ -3890,10 +3890,10 @@
Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName());
}
// uncompress the binary to its eventual destination on /data
- final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getCodePath());
+ final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath());
if (scanFile == null) {
throw new PackageManagerException(
- "Unable to decompress stub at " + stubPkg.getCodePath());
+ "Unable to decompress stub at " + stubPkg.getPath());
}
synchronized (mLock) {
mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
@@ -9261,11 +9261,11 @@
// When upgrading from pre-N MR1, verify the package time stamp using the package
// directory and not the APK file.
final long lastModifiedTime = mIsPreNMR1Upgrade
- ? new File(parsedPackage.getCodePath()).lastModified()
+ ? new File(parsedPackage.getPath()).lastModified()
: getLastModifiedTime(parsedPackage);
final VersionInfo settingsVersionForPackage = getSettingsVersionForPackage(parsedPackage);
if (ps != null && !forceCollect
- && ps.getCodePathString().equals(parsedPackage.getCodePath())
+ && ps.getPathString().equals(parsedPackage.getPath())
&& ps.timeStamp == lastModifiedTime
&& !isCompatSignatureUpdateNeeded(settingsVersionForPackage)
&& !isRecoverSignatureUpdateNeeded(settingsVersionForPackage)) {
@@ -9283,8 +9283,8 @@
Slog.w(TAG, "PackageSetting for " + ps.name
+ " is missing signatures. Collecting certs again to recover them.");
} else {
- Slog.i(TAG, parsedPackage.getCodePath() + " changed; collecting certs" +
- (forceCollect ? " (forced)" : ""));
+ Slog.i(TAG, parsedPackage.getPath() + " changed; collecting certs"
+ + (forceCollect ? " (forced)" : ""));
}
try {
@@ -9368,7 +9368,7 @@
* Returns if forced apk verification can be skipped for the whole package, including splits.
*/
private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
- if (!canSkipForcedApkVerification(pkg.getBaseCodePath())) {
+ if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
return false;
}
// TODO: Allow base and splits to be verified individually.
@@ -9499,7 +9499,7 @@
}
final boolean newPkgChangedPaths = pkgAlreadyExists
- && !pkgSetting.getCodePathString().equals(parsedPackage.getCodePath());
+ && !pkgSetting.getPathString().equals(parsedPackage.getPath());
final boolean newPkgVersionGreater =
pkgAlreadyExists && parsedPackage.getLongVersionCode() > pkgSetting.versionCode;
final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
@@ -9518,11 +9518,11 @@
"System package updated;"
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> " + parsedPackage.getLongVersionCode()
- + "; " + pkgSetting.getCodePathString()
- + " --> " + parsedPackage.getCodePath());
+ + "; " + pkgSetting.getPathString()
+ + " --> " + parsedPackage.getPath());
final InstallArgs args = createInstallArgsForExisting(
- pkgSetting.getCodePathString(), getAppDexInstructionSets(
+ pkgSetting.getPathString(), getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
args.cleanUpResourcesLI();
synchronized (mLock) {
@@ -9535,7 +9535,7 @@
// equal to the version on the /data partition. Throw an exception and use
// the application already installed on the /data partition.
throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName()
- + " at " + parsedPackage.getCodePath() + " ignored: updated version "
+ + " at " + parsedPackage.getPath() + " ignored: updated version "
+ pkgSetting.versionCode + " better than this "
+ parsedPackage.getLongVersionCode());
}
@@ -9597,10 +9597,10 @@
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> "
+ parsedPackage.getLongVersionCode()
- + "; " + pkgSetting.getCodePathString() + " --> "
- + parsedPackage.getCodePath());
+ + "; " + pkgSetting.getPathString() + " --> "
+ + parsedPackage.getPath());
InstallArgs args = createInstallArgsForExisting(
- pkgSetting.getCodePathString(), getAppDexInstructionSets(
+ pkgSetting.getPathString(), getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
@@ -9613,10 +9613,10 @@
logCriticalInfo(Log.INFO,
"System package disabled;"
+ " name: " + pkgSetting.name
- + "; old: " + pkgSetting.getCodePathString() + " @ "
+ + "; old: " + pkgSetting.getPathString() + " @ "
+ pkgSetting.versionCode
- + "; new: " + parsedPackage.getCodePath() + " @ "
- + parsedPackage.getCodePath());
+ + "; new: " + parsedPackage.getPath() + " @ "
+ + parsedPackage.getPath());
}
}
@@ -9797,7 +9797,7 @@
* Return the prebuilt profile path given a package base code path.
*/
private static String getPrebuildProfilePath(AndroidPackage pkg) {
- return pkg.getBaseCodePath() + ".prof";
+ return pkg.getBaseApkPath() + ".prof";
}
/**
@@ -11450,7 +11450,7 @@
if (changedAbiCodePath == null) {
changedAbiCodePath = new ArrayList<>();
}
- changedAbiCodePath.add(ps.getCodePathString());
+ changedAbiCodePath.add(ps.getPathString());
}
}
}
@@ -11545,7 +11545,7 @@
}
// Initialize package source and resource directories
- final File destCodeFile = new File(parsedPackage.getCodePath());
+ final File destCodeFile = new File(parsedPackage.getPath());
// We keep references to the derived CPU Abis from settings in oder to reuse
// them in the case where we're not upgrading or booting for the first time.
@@ -11883,9 +11883,9 @@
private static void assertCodePolicy(AndroidPackage pkg)
throws PackageManagerException {
final boolean shouldHaveCode = pkg.isHasCode();
- if (shouldHaveCode && !apkHasCode(pkg.getBaseCodePath())) {
+ if (shouldHaveCode && !apkHasCode(pkg.getBaseApkPath())) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Package " + pkg.getBaseCodePath() + " code is missing");
+ "Package " + pkg.getBaseApkPath() + " code is missing");
}
if (!ArrayUtils.isEmpty(pkg.getSplitCodePaths())) {
@@ -11917,7 +11917,7 @@
if (parsedPackage.isDirectBootAware()) {
parsedPackage.setAllComponentsDirectBootAware(true);
}
- if (compressedFileExists(parsedPackage.getCodePath())) {
+ if (compressedFileExists(parsedPackage.getPath())) {
parsedPackage.setStub(true);
}
} else {
@@ -12008,7 +12008,7 @@
assertCodePolicy(pkg);
}
- if (pkg.getCodePath() == null) {
+ if (pkg.getPath() == null) {
// Bail out. The resource and code paths haven't been set.
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Code and resource paths haven't been set correctly");
@@ -12035,7 +12035,7 @@
if (mAndroidApplication != null) {
Slog.w(TAG, "*************************************************");
Slog.w(TAG, "Core android package being redefined. Skipping.");
- Slog.w(TAG, " codePath=" + pkg.getCodePath());
+ Slog.w(TAG, " codePath=" + pkg.getPath());
Slog.w(TAG, "*************************************************");
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Core android package being redefined. Skipping.");
@@ -12191,14 +12191,14 @@
PackageSetting known = mSettings.getPackageLPr(pkg.getPackageName());
if (known != null) {
if (DEBUG_PACKAGE_SCANNING) {
- Log.d(TAG, "Examining " + pkg.getCodePath()
- + " and requiring known path " + known.getCodePathString());
+ Log.d(TAG, "Examining " + pkg.getPath()
+ + " and requiring known path " + known.getPathString());
}
- if (!pkg.getCodePath().equals(known.getCodePathString())) {
+ if (!pkg.getPath().equals(known.getPathString())) {
throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
"Application package " + pkg.getPackageName()
- + " found at " + pkg.getCodePath()
- + " but expected at " + known.getCodePathString()
+ + " found at " + pkg.getPath()
+ + " but expected at " + known.getPathString()
+ "; ignoring.");
}
} else {
@@ -14532,13 +14532,11 @@
Log.v(TAG, "restoreAndPostInstall userId=" + userId + " package=" + res.pkg);
}
- // A restore should be performed at this point if (a) the install
- // succeeded, (b) the operation is not an update, and (c) the new
- // package has not opted out of backup participation.
+ // A restore should be requested at this point if (a) the install
+ // succeeded, (b) the operation is not an update.
final boolean update = res.removedInfo != null
&& res.removedInfo.removedPackage != null;
- boolean allowBackup = res.pkg != null && res.pkg.isAllowBackup();
- boolean doRestore = !update && allowBackup;
+ boolean doRestore = !update && res.pkg != null;
// Set up the post-install work request bookkeeping. This will be used
// and cleaned up by the post-install event handling regardless of whether
@@ -15787,7 +15785,7 @@
abstract boolean doRename(int status, ParsedPackage parsedPackage);
abstract int doPostInstall(int status, int uid);
- /** @see PackageSettingBase#getCodePath() */
+ /** @see PackageSettingBase#getPath() */
abstract String getCodePath();
// Need installer lock especially for dex file removal.
@@ -15968,7 +15966,7 @@
return false;
}
parsedPackage.setBaseCodePath(FileUtils.rewriteAfterRename(beforeCodeFile,
- afterCodeFile, parsedPackage.getBaseCodePath()));
+ afterCodeFile, parsedPackage.getBaseApkPath()));
parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
afterCodeFile, parsedPackage.getSplitCodePaths()));
@@ -16235,7 +16233,7 @@
InstallSource installSource = installArgs.installSource;
final String installerPackageName = installSource.installerPackageName;
- if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getCodePath());
+ if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath());
synchronized (mLock) {
// NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
mPermissionManager.updatePermissions(pkgName, pkg);
@@ -16874,7 +16872,7 @@
// which means we are replacing another update that is already
// installed. We need to make sure to delete the older one's .apk.
res.removedInfo.args = createInstallArgsForExisting(
- oldPackage.getCodePath(),
+ oldPackage.getPath(),
getAppDexInstructionSets(
AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
deletedPkgSetting),
@@ -16917,7 +16915,7 @@
if (ps1.mOldCodePaths == null) {
ps1.mOldCodePaths = new ArraySet<>();
}
- Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseCodePath());
+ Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseApkPath());
if (oldPackage.getSplitCodePaths() != null) {
Collections.addAll(ps1.mOldCodePaths, oldPackage.getSplitCodePaths());
}
@@ -17082,7 +17080,7 @@
// For incremental installs, we bypass the verifier prior to install. Now
// that we know the package is valid, send a notice to the verifier with
// the root hash of the base.apk.
- final String baseCodePath = request.installResult.pkg.getBaseCodePath();
+ final String baseCodePath = request.installResult.pkg.getBaseApkPath();
final String[] splitCodePaths = request.installResult.pkg.getSplitCodePaths();
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
final int verificationId = mPendingVerificationToken++;
@@ -17127,9 +17125,9 @@
final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg;
final String packageName = pkg.getPackageName();
final boolean onIncremental = mIncrementalManager != null
- && isIncrementalPath(pkg.getCodePath());
+ && isIncrementalPath(pkg.getPath());
if (onIncremental) {
- IncrementalStorage storage = mIncrementalManager.openStorage(pkg.getCodePath());
+ IncrementalStorage storage = mIncrementalManager.openStorage(pkg.getPath());
if (storage == null) {
throw new IllegalArgumentException(
"Install: null storage for incremental package " + packageName);
@@ -17143,7 +17141,7 @@
}
if (reconciledPkg.prepareResult.replace) {
mDexManager.notifyPackageUpdated(pkg.getPackageName(),
- pkg.getBaseCodePath(), pkg.getSplitCodePaths());
+ pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
// Prepare the application profiles for the new code paths.
@@ -17739,12 +17737,10 @@
if (parsedPackage.isStaticSharedLibrary()) {
// Static libs have a synthetic package name containing the version
// and cannot be updated as an update would get a new package name,
- // unless this is the exact same version code which is useful for
- // development.
+ // unless this is installed from adb which is useful for development.
AndroidPackage existingPkg = mPackages.get(parsedPackage.getPackageName());
if (existingPkg != null
- && existingPkg.getLongVersionCode()
- != parsedPackage.getLongVersionCode()) {
+ && (installFlags & PackageManager.INSTALL_FROM_ADB) == 0) {
throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Packages declaring "
+ "static-shared libs cannot be updated");
@@ -17763,7 +17759,6 @@
oldPackage = mPackages.get(pkgName11);
existingPackage = oldPackage;
if (DEBUG_INSTALL) {
- // TODO(b/135203078): PackageImpl.toString()
Slog.d(TAG,
"replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage);
}
@@ -17797,7 +17792,7 @@
final byte[] digestBytes;
try {
final MessageDigest digest = MessageDigest.getInstance("SHA-512");
- updateDigest(digest, new File(parsedPackage.getBaseCodePath()));
+ updateDigest(digest, new File(parsedPackage.getBaseApkPath()));
if (!ArrayUtils.isEmpty(parsedPackage.getSplitCodePaths())) {
for (String path : parsedPackage.getSplitCodePaths()) {
updateDigest(digest, new File(path));
@@ -17977,7 +17972,7 @@
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
if (ps != null && ps.isPrivileged()) {
- fsverityCandidates.put(pkg.getBaseCodePath(), null);
+ fsverityCandidates.put(pkg.getBaseApkPath(), null);
if (pkg.getSplitCodePaths() != null) {
for (String splitPath : pkg.getSplitCodePaths()) {
fsverityCandidates.put(splitPath, null);
@@ -17988,11 +17983,11 @@
} else {
// NB: These files will become only accessible if the signing key is loaded in kernel's
// .fs-verity keyring.
- fsverityCandidates.put(pkg.getBaseCodePath(),
- VerityUtils.getFsveritySignatureFilePath(pkg.getBaseCodePath()));
+ fsverityCandidates.put(pkg.getBaseApkPath(),
+ VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
- pkg.getBaseCodePath());
+ pkg.getBaseApkPath());
if (new File(dmPath).exists()) {
fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
}
@@ -19103,7 +19098,7 @@
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
try {
- installPackageFromSystemLIF(disabledPs.getCodePathString(), allUserHandles,
+ installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles,
outInfo == null ? null : outInfo.origUsers, writeSettings);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPkg.getPackageName() + ": "
@@ -19228,7 +19223,7 @@
// Delete application code and resources only for parent packages
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(
- ps.getCodePathString(), getAppDexInstructionSets(
+ ps.getPathString(), getAppDexInstructionSets(
ps.primaryCpuAbiString, ps.secondaryCpuAbiString));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
@@ -19770,7 +19765,7 @@
final String[] packageNames = { packageName };
final long[] ceDataInodes = { ps.getCeDataInode(userId) };
- final String[] codePaths = { ps.getCodePathString() };
+ final String[] codePaths = { ps.getPathString() };
try {
mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0,
@@ -21633,6 +21628,8 @@
.getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_ALL);
co.onChange(true);
+ mAppsFilter.onSystemReady();
+
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(
@@ -21781,9 +21778,6 @@
mInstallerService.restoreAndApplyStagedSessionIfNeeded();
mExistingPackages = null;
-
- // We'll do this last as it builds its cache while holding mLock via callback.
- mAppsFilter.onSystemReady();
}
public void waitForAppDataPrepared() {
@@ -22697,11 +22691,11 @@
synchronized (mInstallLock) {
final AndroidPackage pkg;
try {
- pkg = scanPackageTracedLI(ps.getCodePath(), parseFlags, SCAN_INITIAL, 0, null);
+ pkg = scanPackageTracedLI(ps.getPath(), parseFlags, SCAN_INITIAL, 0, null);
loaded.add(pkg);
} catch (PackageManagerException e) {
- Slog.w(TAG, "Failed to scan " + ps.getCodePath() + ": " + e.getMessage());
+ Slog.w(TAG, "Failed to scan " + ps.getPath() + ": " + e.getMessage());
}
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
@@ -22788,7 +22782,7 @@
false, null)) {
unloaded.add(pkg);
} else {
- Slog.w(TAG, "Failed to unload " + ps.getCodePath());
+ Slog.w(TAG, "Failed to unload " + ps.getPath());
}
}
@@ -22842,7 +22836,7 @@
final int packageCount = mSettings.mPackages.size();
for (int i = 0; i < packageCount; i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
- codePaths.add(ps.getCodePath().getAbsolutePath());
+ codePaths.add(ps.getPath().getAbsolutePath());
}
return codePaths;
}
@@ -23418,7 +23412,7 @@
currentVolumeUuid = ps.volumeUuid;
- final File probe = new File(pkg.getCodePath());
+ final File probe = new File(pkg.getPath());
final File probeOat = new File(probe, "oat");
if (!probe.isDirectory() || !probeOat.isDirectory()) {
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
@@ -23440,7 +23434,7 @@
}
isCurrentLocationExternal = pkg.isExternalStorage();
- codeFile = new File(pkg.getCodePath());
+ codeFile = new File(pkg.getPath());
installSource = ps.installSource;
packageAbiOverride = ps.cpuAbiOverrideString;
appId = UserHandle.getAppId(pkg.getUid());
@@ -24871,7 +24865,7 @@
mApexManager.getApksInApex(apexPackages.get(i).packageName);
for (int j = 0, apksInApex = apkNames.size(); j < apksInApex; j++) {
final AndroidPackage pkg = getPackage(apkNames.get(j));
- cacher.cleanCachedResult(new File(pkg.getCodePath()));
+ cacher.cleanCachedResult(new File(pkg.getPath()));
}
}
}
@@ -24947,7 +24941,7 @@
Slog.e(TAG, "failed to find package " + packageName);
return false;
}
- overlayPaths.add(pkg.getBaseCodePath());
+ overlayPaths.add(pkg.getBaseApkPath());
}
}
@@ -25663,7 +25657,7 @@
pkgSetting.getPkgState().isUpdatedSystemApp())) {
return null;
}
- File codePath = new File(pkg.getCodePath());
+ File codePath = new File(pkg.getPath());
if (codePath.isDirectory()) {
return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 5553cd0..e5dad85 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -326,11 +326,11 @@
}
public static long getLastModifiedTime(AndroidPackage pkg) {
- final File srcFile = new File(pkg.getCodePath());
+ final File srcFile = new File(pkg.getPath());
if (!srcFile.isDirectory()) {
return srcFile.lastModified();
}
- final File baseFile = new File(pkg.getBaseCodePath());
+ final File baseFile = new File(pkg.getBaseApkPath());
long maxModifiedTime = baseFile.lastModified();
if (pkg.getSplitCodePaths() != null) {
for (int i = pkg.getSplitCodePaths().length - 1; i >=0; --i) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index a3a7273..4476e8a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -44,8 +44,33 @@
public class PackageSetting extends PackageSettingBase {
int appId;
+ /**
+ * This can be null whenever a physical APK on device is missing. This can be the result of
+ * removing an external storage device where the APK resides.
+ *
+ * This will result in the system reading the {@link PackageSetting} from disk, but without
+ * being able to parse the base APK's AndroidManifest.xml to read all of its metadata. The data
+ * that is written and read in {@link Settings} includes a minimal set of metadata needed to
+ * perform other checks in the system.
+ *
+ * This is important in order to enforce uniqueness within the system, as the package, even if
+ * on a removed storage device, is still considered installed. Another package of the same
+ * application ID or declaring the same permissions or similar cannot be installed.
+ *
+ * Re-attaching the storage device to make the APK available should allow the user to use the
+ * app once the device reboots or otherwise re-scans it.
+ *
+ * It is expected that all code that uses a {@link PackageSetting} understands this inner field
+ * may be null. Note that this relationship only works one way. It should not be possible to
+ * have an entry inside {@link PackageManagerService#mPackages} without a corresponding
+ * {@link PackageSetting} inside {@link Settings#mPackages}.
+ *
+ * @deprecated Use {@link #getPkg()}. The setter is favored to avoid unintended mutation.
+ */
@Nullable
+ @Deprecated
public AndroidPackage pkg;
+
/**
* WARNING. The object reference is important. We perform integer equality and NOT
* object equality to check whether shared user settings are the same.
@@ -104,6 +129,12 @@
doCopy(orig);
}
+ /** @see #pkg **/
+ @Nullable
+ public AndroidPackage getPkg() {
+ return pkg;
+ }
+
public int getSharedUserId() {
if (sharedUser != null) {
return sharedUser.userId;
@@ -200,7 +231,6 @@
return installPermissionsFixed;
}
- // TODO(b/135203078): Remove these in favor of reading from the package directly
public boolean isPrivileged() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 6010344..a7bbf8d 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -40,6 +40,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.File;
import java.util.Arrays;
@@ -59,13 +60,9 @@
public final String name;
final String realName;
- /**
- * Path where this package was found on disk. For monolithic packages
- * this is path to single base APK file; for cluster packages this is
- * path to the cluster directory.
- */
- private File mCodePath;
- private String mCodePathString;
+ /** @see AndroidPackage#getPath() */
+ private File mPath;
+ private String mPathString;
String[] usesStaticLibraries;
long[] usesStaticLibrariesVersions;
@@ -136,7 +133,7 @@
boolean forceQueryableOverride;
- PackageSettingBase(String name, String realName, @NonNull File codePath,
+ PackageSettingBase(String name, String realName, @NonNull File path,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString,
long pVersionCode, int pkgFlags, int pkgPrivateFlags,
@@ -146,7 +143,7 @@
this.realName = realName;
this.usesStaticLibraries = usesStaticLibraries;
this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
- setCodePath(codePath);
+ setPath(path);
this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
this.primaryCpuAbiString = primaryCpuAbiString;
this.secondaryCpuAbiString = secondaryCpuAbiString;
@@ -230,7 +227,7 @@
}
private void doCopy(PackageSettingBase orig) {
- setCodePath(orig.getCodePath());
+ setPath(orig.getPath());
cpuAbiOverrideString = orig.cpuAbiOverrideString;
firstInstallTime = orig.firstInstallTime;
installPermissionsFixed = orig.installPermissionsFixed;
@@ -697,18 +694,23 @@
return userState.harmfulAppWarning;
}
- PackageSettingBase setCodePath(@NonNull File codePath) {
- this.mCodePath = codePath;
- this.mCodePathString = codePath.toString();
+ /**
+ * @see #mPath
+ */
+ PackageSettingBase setPath(@NonNull File path) {
+ this.mPath = path;
+ this.mPathString = path.toString();
return this;
}
- File getCodePath() {
- return mCodePath;
+ /** @see #mPath */
+ File getPath() {
+ return mPath;
}
- String getCodePathString() {
- return mCodePathString;
+ /** @see #mPath */
+ String getPathString() {
+ return mPathString;
}
/**
@@ -733,7 +735,7 @@
protected PackageSettingBase updateFrom(PackageSettingBase other) {
super.copyFrom(other);
- setCodePath(other.getCodePath());
+ setPath(other.getPath());
this.usesStaticLibraries = other.usesStaticLibraries;
this.usesStaticLibrariesVersions = other.usesStaticLibrariesVersions;
this.legacyNativeLibraryPathString = other.legacyNativeLibraryPathString;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index bd8d0c8..74bc49d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -306,8 +306,8 @@
private final ArrayMap<String, KernelPackageState> mKernelMapping = new ArrayMap<>();
// List of replaced system applications
- private final ArrayMap<String, PackageSetting> mDisabledSysPackages =
- new ArrayMap<String, PackageSetting>();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ final ArrayMap<String, PackageSetting> mDisabledSysPackages = new ArrayMap<>();
/** List of packages that are blocked for uninstall for specific users */
private final SparseArray<ArraySet<String>> mBlockUninstallPackages = new SparseArray<>();
@@ -538,7 +538,7 @@
return null;
}
p.getPkgState().setUpdatedSystemApp(false);
- PackageSetting ret = addPackageLPw(name, p.realName, p.getCodePath(),
+ PackageSetting ret = addPackageLPw(name, p.realName, p.getPath(),
p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
p.secondaryCpuAbiString, p.cpuAbiOverrideString,
p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
@@ -645,7 +645,7 @@
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ pkgName + " is adopting original package " + originalPkg.name);
pkgSetting = new PackageSetting(originalPkg, pkgName /*realPkgName*/);
- pkgSetting.setCodePath(codePath);
+ pkgSetting.setPath(codePath);
pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
pkgSetting.pkgFlags = pkgFlags;
pkgSetting.pkgPrivateFlags = pkgPrivateFlags;
@@ -770,12 +770,12 @@
"Updating application package " + pkgName + " failed");
}
- if (!pkgSetting.getCodePath().equals(codePath)) {
+ if (!pkgSetting.getPath().equals(codePath)) {
final boolean isSystem = pkgSetting.isSystem();
Slog.i(PackageManagerService.TAG,
"Update" + (isSystem ? " system" : "")
+ " package " + pkgName
- + " code path from " + pkgSetting.getCodePathString()
+ + " code path from " + pkgSetting.getPathString()
+ " to " + codePath.toString()
+ "; Retain data and using new");
if (!isSystem) {
@@ -797,7 +797,7 @@
// internal to external storage or vice versa.
pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
}
- pkgSetting.setCodePath(codePath);
+ pkgSetting.setPath(codePath);
}
// If what we are scanning is a system (and possibly privileged) package,
// then make it so, regardless of whether it was previously installed only
@@ -2174,32 +2174,24 @@
void readUsesStaticLibLPw(XmlPullParser parser, PackageSetting outPs)
throws IOException, XmlPullParserException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- String libName = parser.getAttributeValue(null, ATTR_NAME);
- String libVersionStr = parser.getAttributeValue(null, ATTR_VERSION);
+ String libName = parser.getAttributeValue(null, ATTR_NAME);
+ String libVersionStr = parser.getAttributeValue(null, ATTR_VERSION);
- long libVersion = -1;
- try {
- libVersion = Long.parseLong(libVersionStr);
- } catch (NumberFormatException e) {
- // ignore
- }
-
- if (libName != null && libVersion >= 0) {
- outPs.usesStaticLibraries = ArrayUtils.appendElement(String.class,
- outPs.usesStaticLibraries, libName);
- outPs.usesStaticLibrariesVersions = ArrayUtils.appendLong(
- outPs.usesStaticLibrariesVersions, libVersion);
- }
-
- XmlUtils.skipCurrentTag(parser);
+ long libVersion = -1;
+ try {
+ libVersion = Long.parseLong(libVersionStr);
+ } catch (NumberFormatException e) {
+ // ignore
}
+
+ if (libName != null && libVersion >= 0) {
+ outPs.usesStaticLibraries = ArrayUtils.appendElement(String.class,
+ outPs.usesStaticLibraries, libName);
+ outPs.usesStaticLibrariesVersions = ArrayUtils.appendLong(
+ outPs.usesStaticLibrariesVersions, libVersion);
+ }
+
+ XmlUtils.skipCurrentTag(parser);
}
void writeUsesStaticLibLPw(XmlSerializer serializer, String[] usesStaticLibraries,
@@ -2710,7 +2702,7 @@
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
- serializer.attribute(null, "codePath", pkg.getCodePathString());
+ serializer.attribute(null, "codePath", pkg.getPathString());
serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
@@ -2752,7 +2744,7 @@
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
- serializer.attribute(null, "codePath", pkg.getCodePathString());
+ serializer.attribute(null, "codePath", pkg.getPathString());
if (pkg.legacyNativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
@@ -3875,6 +3867,8 @@
readDomainVerificationLPw(parser, packageSetting);
} else if (tagName.equals(TAG_MIME_GROUP)) {
packageSetting.mimeGroups = readMimeGroupLPw(parser, packageSetting.mimeGroups);
+ } else if (tagName.equals(TAG_USES_STATIC_LIB)) {
+ readUsesStaticLibLPw(parser, packageSetting);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unknown element under <package>: " + parser.getName());
@@ -4561,9 +4555,9 @@
pw.print(prefix); pw.print(" sharedUser="); pw.println(ps.sharedUser);
}
pw.print(prefix); pw.print(" pkg="); pw.println(pkg);
- pw.print(prefix); pw.print(" codePath="); pw.println(ps.getCodePathString());
+ pw.print(prefix); pw.print(" codePath="); pw.println(ps.getPathString());
if (permissionNames == null) {
- pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getCodePathString());
+ pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getPathString());
pw.print(prefix); pw.print(" legacyNativeLibraryDir=");
pw.println(ps.legacyNativeLibraryPathString);
pw.print(prefix); pw.print(" extractNativeLibs=");
@@ -4581,10 +4575,10 @@
pw.println();
if (pkg != null) {
pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName());
+ pw.print(prefix); pw.print(" usesNonSdkApi="); pw.println(pkg.isUsesNonSdkApi());
pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, pkg); pw.println();
final int apkSigningVersion = pkg.getSigningDetails().signatureSchemeVersion;
pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion);
- // TODO(b/135203078): Is there anything to print here with AppInfo removed?
pw.print(prefix); pw.print(" applicationInfo=");
pw.println(pkg.toAppInfoToString());
pw.print(prefix); pw.print(" flags=");
@@ -5180,7 +5174,6 @@
}
void dumpComponents(PrintWriter pw, String prefix, PackageSetting ps) {
- // TODO(b/135203078): ParsedComponent toString methods for dumping
dumpComponents(pw, prefix, "activities:", ps.pkg.getActivities());
dumpComponents(pw, prefix, "services:", ps.pkg.getServices());
dumpComponents(pw, prefix, "receivers:", ps.pkg.getReceivers());
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 8000c63..587cb825 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -486,7 +486,7 @@
public boolean compileLayouts(AndroidPackage pkg) {
try {
final String packageName = pkg.getPackageName();
- final String apkPath = pkg.getBaseCodePath();
+ final String apkPath = pkg.getBaseApkPath();
// TODO(b/143971007): Use a cross-user directory
File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId());
final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
@@ -524,7 +524,7 @@
private ArrayMap<String, String> getPackageProfileNames(AndroidPackage pkg) {
ArrayMap<String, String> result = new ArrayMap<>();
if (pkg.isHasCode()) {
- result.put(pkg.getBaseCodePath(), ArtManager.getProfileName(null));
+ result.put(pkg.getBaseApkPath(), ArtManager.getProfileName(null));
}
String[] splitCodePaths = pkg.getSplitCodePaths();
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index 6807388..fa01836 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -18,12 +18,12 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.SharedLibraryInfo;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.File;
import java.util.List;
@@ -90,7 +90,7 @@
// The splits have an implicit dependency on the base apk.
// This means that we have to add the base apk file in addition to the shared libraries.
- String baseApkName = new File(pkg.getBaseCodePath()).getName();
+ String baseApkName = new File(pkg.getBaseApkPath()).getName();
String baseClassPath = baseApkName;
// The result is stored in classLoaderContexts.
@@ -401,7 +401,7 @@
* Assumes that the application declares a non-null array of splits.
*/
private static String[] getSplitRelativeCodePaths(AndroidPackage pkg) {
- String baseCodePath = new File(pkg.getBaseCodePath()).getParent();
+ String baseCodePath = new File(pkg.getBaseApkPath()).getParent();
String[] splitCodePaths = pkg.getSplitCodePaths();
String[] splitRelativeCodePaths = new String[ArrayUtils.size(splitCodePaths)];
for (int i = 0; i < splitRelativeCodePaths.length; i++) {
diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
index 5506a52..a567266 100644
--- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java
+++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
@@ -40,7 +40,7 @@
public boolean compileLayouts(AndroidPackage pkg) {
try {
final String packageName = pkg.getPackageName();
- final String apkPath = pkg.getBaseCodePath();
+ final String apkPath = pkg.getBaseApkPath();
// TODO(b/143971007): Use a cross-user directory
File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId());
final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index 99c6dd1..74ec161 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -79,7 +79,6 @@
final PackageParserCacheHelper.ReadHelper helper = new PackageParserCacheHelper.ReadHelper(p);
helper.startAndInstall();
- // TODO(b/135203078): Hide PackageImpl constructor?
ParsedPackage pkg = new PackageImpl(p);
p.recycle();
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 09b4f89..d695a01 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -35,6 +35,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.ParsingUtils;
import android.content.pm.parsing.component.ComponentParseUtils;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedComponent;
@@ -73,7 +74,7 @@
* @hide
**/
public class PackageInfoUtils {
- private static final String TAG = PackageParser2.TAG;
+ private static final String TAG = ParsingUtils.TAG;
/**
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
@@ -207,7 +208,6 @@
public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
@PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
@Nullable PackageSetting pkgSetting) {
- // TODO(b/135203078): Consider cases where we don't have a PkgSetting
if (pkg == null) {
return null;
}
@@ -354,7 +354,6 @@
return null;
}
- // TODO(b/135203078): Add setting related state
info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting);
info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting);
info.nativeLibraryDir = pkg.getNativeLibraryDir();
@@ -454,7 +453,6 @@
/** @see ApplicationInfo#flags */
public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
- // TODO(b/135203078): Add setting related state
// @formatter:off
int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoFlags(pkg)
| flag(pkg.isSystem(), ApplicationInfo.FLAG_SYSTEM)
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
index 1145057..851ddd1 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -71,7 +71,7 @@
return platformCompat.isChangeEnabled(changeId, appInfo);
} catch (Exception e) {
// This shouldn't happen, but assume enforcement if it does
- Slog.wtf(ParsingUtils.TAG, "IPlatformCompat query failed", e);
+ Slog.wtf(TAG, "IPlatformCompat query failed", e);
return true;
}
}
@@ -87,7 +87,7 @@
});
}
- static final String TAG = "PackageParser2";
+ private static final String TAG = ParsingUtils.TAG;
private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
index 39784cf..a13680a 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
@@ -23,7 +23,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
-import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ParsingPackageRead;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -65,18 +64,16 @@
/** Path of base APK */
@NonNull
- String getBaseCodePath();
+ String getBaseApkPath();
/** Revision code of base APK */
int getBaseRevisionCode();
/**
- * Path where this package was found on disk. For monolithic packages
- * this is path to single base APK file; for cluster packages this is
- * path to the cluster directory.
+ * The path to the folder containing the base APK and any installed splits.
*/
@NonNull
- String getCodePath();
+ String getPath();
/**
* Permissions requested but not in the manifest. These may have been split or migrated from
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index a6f02e7..0a56e13 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -58,7 +58,7 @@
PackageImpl pkg = (PackageImpl) aPkg;
ArrayList<String> paths = new ArrayList<>();
if (pkg.isHasCode()) {
- paths.add(pkg.getBaseCodePath());
+ paths.add(pkg.getBaseApkPath());
}
String[] splitCodePaths = pkg.getSplitCodePaths();
if (!ArrayUtils.isEmpty(splitCodePaths)) {
@@ -77,7 +77,7 @@
public static List<String> getAllCodePaths(AndroidPackage aPkg) {
PackageImpl pkg = (PackageImpl) aPkg;
ArrayList<String> paths = new ArrayList<>();
- paths.add(pkg.getBaseCodePath());
+ paths.add(pkg.getBaseApkPath());
String[] splitCodePaths = pkg.getSplitCodePaths();
if (!ArrayUtils.isEmpty(splitCodePaths)) {
@@ -147,7 +147,7 @@
if (pkg.isSystem() && !isUpdatedSystemApp) {
return false;
}
- if (IncrementalManager.isIncrementalPath(pkg.getCodePath())) {
+ if (IncrementalManager.isIncrementalPath(pkg.getPath())) {
return false;
}
return true;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 43365fa..0e3e110 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -136,9 +136,9 @@
private int uid = -1;
@VisibleForTesting
- public PackageImpl(@NonNull String packageName, @NonNull String baseCodePath,
- @NonNull String codePath, @Nullable TypedArray manifestArray, boolean isCoreApp) {
- super(packageName, baseCodePath, codePath, manifestArray);
+ public PackageImpl(@NonNull String packageName, @NonNull String baseApkPath,
+ @NonNull String path, @Nullable TypedArray manifestArray, boolean isCoreApp) {
+ super(packageName, baseApkPath, path, manifestArray);
this.manifestPackageName = this.packageName;
this.coreApp = isCoreApp;
}
@@ -247,7 +247,7 @@
@Override
public PackageImpl setCodePath(@NonNull String value) {
- this.codePath = value;
+ this.mPath = value;
return this;
}
@@ -322,7 +322,7 @@
@Override
public PackageImpl setBaseCodePath(@NonNull String baseCodePath) {
- this.baseCodePath = TextUtils.safeIntern(baseCodePath);
+ this.mBaseApkPath = TextUtils.safeIntern(baseCodePath);
return this;
}
@@ -430,7 +430,7 @@
@Deprecated
@Override
public String toAppInfoToString() {
- return "ApplicationInfo{"
+ return "PackageImpl{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + getPackageName() + "}";
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index ffdcc22..1cfc5b1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3526,7 +3526,7 @@
deniedPermissions == null || !deniedPermissions.contains(perm);
if (permissionViolation) {
Slog.w(TAG, "Privileged permission " + perm + " for package "
- + pkg.getPackageName() + " (" + pkg.getCodePath()
+ + pkg.getPackageName() + " (" + pkg.getPath()
+ ") not in privapp-permissions whitelist");
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
@@ -3534,7 +3534,7 @@
mPrivappPermissionsViolations = new ArraySet<>();
}
mPrivappPermissionsViolations.add(
- pkg.getPackageName() + " (" + pkg.getCodePath() + "): "
+ pkg.getPackageName() + " (" + pkg.getPath() + "): "
+ perm);
}
} else {
diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
index 8af76a1..c769a50 100644
--- a/services/core/java/com/android/server/search/Searchables.java
+++ b/services/core/java/com/android/server/search/Searchables.java
@@ -20,6 +20,7 @@
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -397,8 +398,9 @@
}
private String getGlobalSearchProviderSetting() {
- return Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY);
+ final ContentResolver cr = mContext.getContentResolver();
+ return Settings.Secure.getStringForUser(cr,
+ Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY, cr.getUserId());
}
/**
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 5aedfc1..2a74b3d 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -28,6 +28,8 @@
import android.Manifest.permission;
import android.annotation.NonNull;
import android.app.AppOpsManager;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceSpec;
import android.app.usage.UsageStatsManagerInternal;
@@ -39,7 +41,9 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -61,6 +65,7 @@
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -72,7 +77,10 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
public class SliceManagerService extends ISliceManager.Stub {
@@ -80,13 +88,16 @@
private final Object mLock = new Object();
private final Context mContext;
+ private final PackageManagerInternal mPackageManagerInternal;
private final AppOpsManager mAppOps;
private final AssistUtils mAssistUtils;
@GuardedBy("mLock")
private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>();
@GuardedBy("mLock")
- private final SparseArray<String> mLastAssistantPackage = new SparseArray<>();
+ private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>();
private final Handler mHandler;
private final SlicePermissionManager mPermissions;
@@ -99,6 +110,8 @@
@VisibleForTesting
SliceManagerService(Context context, Looper looper) {
mContext = context;
+ mPackageManagerInternal = Objects.requireNonNull(
+ LocalServices.getService(PackageManagerInternal.class));
mAppOps = context.getSystemService(AppOpsManager.class);
mAssistUtils = new AssistUtils(context);
mHandler = new Handler(looper);
@@ -111,6 +124,7 @@
filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
+ mRoleObserver = new RoleObserver();
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
}
@@ -160,7 +174,8 @@
mHandler.post(() -> {
if (slicePkg != null && !Objects.equals(pkg, slicePkg)) {
mAppUsageStats.reportEvent(slicePkg, user,
- isAssistant(pkg, user) ? SLICE_PINNED_PRIV : SLICE_PINNED);
+ isAssistant(pkg, user) || isDefaultHomeApp(pkg, user)
+ ? SLICE_PINNED_PRIV : SLICE_PINNED);
}
});
}
@@ -425,19 +440,38 @@
private boolean hasFullSliceAccess(String pkg, int userId) {
long ident = Binder.clearCallingIdentity();
try {
- return isAssistant(pkg, userId) || isGrantedFullAccess(pkg, userId);
+ boolean ret = isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId)
+ || isGrantedFullAccess(pkg, userId);
+ return ret;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private boolean isAssistant(String pkg, int userId) {
- if (pkg == null) return false;
- if (!pkg.equals(mLastAssistantPackage.get(userId))) {
- // Failed on cached value, try updating.
- mLastAssistantPackage.put(userId, getAssistant(userId));
+ return getAssistantMatcher(userId).matches(pkg);
+ }
+
+ private boolean isDefaultHomeApp(String pkg, int userId) {
+ return getHomeMatcher(userId).matches(pkg);
+ }
+
+ private PackageMatchingCache getAssistantMatcher(int userId) {
+ PackageMatchingCache matcher = mAssistantLookup.get(userId);
+ if (matcher == null) {
+ matcher = new PackageMatchingCache(() -> getAssistant(userId));
+ mAssistantLookup.put(userId, matcher);
}
- return pkg.equals(mLastAssistantPackage.get(userId));
+ return matcher;
+ }
+
+ private PackageMatchingCache getHomeMatcher(int userId) {
+ PackageMatchingCache matcher = mHomeLookup.get(userId);
+ if (matcher == null) {
+ matcher = new PackageMatchingCache(() -> getDefaultHome(userId));
+ mHomeLookup.put(userId, matcher);
+ }
+ return matcher;
}
private String getAssistant(int userId) {
@@ -448,6 +482,111 @@
return cn.getPackageName();
}
+ /**
+ * A cached value of the default home app
+ */
+ private String mCachedDefaultHome = null;
+
+ // Based on getDefaultHome in ShortcutService.
+ // TODO: Unify if possible
+ @VisibleForTesting
+ protected String getDefaultHome(int userId) {
+
+ // Set VERIFY to true to run the cache in "shadow" mode for cache
+ // testing. Do not commit set to true;
+ final boolean VERIFY = false;
+
+ if (mCachedDefaultHome != null) {
+ if (!VERIFY) {
+ return mCachedDefaultHome;
+ }
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+
+ // Default launcher from package manager.
+ final ComponentName defaultLauncher = mPackageManagerInternal
+ .getHomeActivitiesAsUser(allHomeCandidates, userId);
+
+ ComponentName detected = defaultLauncher;
+
+ // Cache the default launcher. It is not a problem if the
+ // launcher is null - eventually, the default launcher will be
+ // set to something non-null.
+ mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null);
+
+ if (detected == null) {
+ // If we reach here, that means it's the first check since the user was created,
+ // and there's already multiple launchers and there's no default set.
+ // Find the system one with the highest priority.
+ // (We need to check the priority too because of FallbackHome in Settings.)
+ // If there's no system launcher yet, then no one can access slices, until
+ // the user explicitly sets one.
+ final int size = allHomeCandidates.size();
+
+ int lastPriority = Integer.MIN_VALUE;
+ for (int i = 0; i < size; i++) {
+ final ResolveInfo ri = allHomeCandidates.get(i);
+ if (!ri.activityInfo.applicationInfo.isSystemApp()) {
+ continue;
+ }
+ if (ri.priority < lastPriority) {
+ continue;
+ }
+ detected = ri.activityInfo.getComponentName();
+ lastPriority = ri.priority;
+ }
+ }
+ final String ret = ((detected != null) ? detected.getPackageName() : null);
+ if (VERIFY) {
+ if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) {
+ Slog.e(TAG, "getDefaultHome() cache failure, is " +
+ mCachedDefaultHome + " should be " + ret);
+ }
+ }
+ return ret;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void invalidateCachedDefaultHome() {
+ mCachedDefaultHome = null;
+ }
+
+ /**
+ * Listen for changes in the roles, and invalidate the cached default
+ * home as necessary.
+ */
+ private RoleObserver mRoleObserver;
+
+ class RoleObserver implements OnRoleHoldersChangedListener {
+ private RoleManager mRm;
+ private final Executor mExecutor;
+
+ RoleObserver() {
+ mExecutor = mContext.getMainExecutor();
+ register();
+ }
+
+ public void register() {
+ mRm = mContext.getSystemService(RoleManager.class);
+ if (mRm != null) {
+ mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
+ invalidateCachedDefaultHome();
+ }
+ }
+
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ if (RoleManager.ROLE_HOME.equals(roleName)) {
+ invalidateCachedDefaultHome();
+ }
+ }
+ }
+
private boolean isGrantedFullAccess(String pkg, int userId) {
return mPermissions.hasFullAccess(pkg, userId);
}
@@ -496,6 +635,30 @@
return mPermissions.getAllPackagesGranted(pkg);
}
+ /**
+ * Holder that caches a package that has access to a slice.
+ */
+ static class PackageMatchingCache {
+
+ private final Supplier<String> mPkgSource;
+ private String mCurrentPkg;
+
+ public PackageMatchingCache(Supplier<String> pkgSource) {
+ mPkgSource = pkgSource;
+ }
+
+ public boolean matches(String pkgCandidate) {
+ if (pkgCandidate == null) return false;
+
+ if (Objects.equals(pkgCandidate, mCurrentPkg)) {
+ return true;
+ }
+ // Failed on cached value, try updating.
+ mCurrentPkg = mPkgSource.get();
+ return Objects.equals(pkgCandidate, mCurrentPkg);
+ }
+ }
+
public static class Lifecycle extends SystemService {
private SliceManagerService mService;
diff --git a/services/core/java/com/android/server/telecom/InternalServiceRepository.java b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
new file mode 100644
index 0000000..76ea5c7
--- /dev/null
+++ b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 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.server.telecom;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Process;
+
+import com.android.internal.telecom.IDeviceIdleControllerAdapter;
+import com.android.internal.telecom.IInternalServiceRetriever;
+import com.android.server.DeviceIdleInternal;
+
+/**
+ * The Telecom APK can not access services stored in LocalService directly and since it is in the
+ * SYSTEM process, it also can not use the *Manager interfaces
+ * (see {@link Context#enforceCallingPermission(String, String)}). Instead, we must wrap these local
+ * services in binder interfaces to allow Telecom access.
+ */
+public class InternalServiceRepository extends IInternalServiceRetriever.Stub {
+
+ private final IDeviceIdleControllerAdapter.Stub mDeviceIdleControllerAdapter =
+ new IDeviceIdleControllerAdapter.Stub() {
+ @Override
+ public void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle,
+ String reason) {
+ mDeviceIdleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
+ duration, userHandle, true /*sync*/, reason);
+ }
+ };
+
+ private final DeviceIdleInternal mDeviceIdleController;
+
+ public InternalServiceRepository(DeviceIdleInternal deviceIdleController) {
+ mDeviceIdleController = deviceIdleController;
+ }
+
+ @Override
+ public IDeviceIdleControllerAdapter getDeviceIdleController() {
+ ensureSystemProcess();
+ return mDeviceIdleControllerAdapter;
+ }
+
+ private void ensureSystemProcess() {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ // Correctness check - this should never happen.
+ throw new SecurityException("SYSTEM ONLY API.");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index a853529..52ad893 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -35,7 +35,10 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.telecom.ITelecomLoader;
+import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.SmsApplication;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;
@@ -53,16 +56,13 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// Normally, we would listen for death here, but since telecom runs in the same process
- // as this loader (process="system") thats redundant here.
+ // as this loader (process="system") that's redundant here.
try {
- service.linkToDeath(new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- connectToTelecom();
- }
- }, 0);
+ ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service);
+ ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo);
+
SmsApplication.getDefaultMmsApplication(mContext, false);
- ServiceManager.addService(Context.TELECOM_SERVICE, service);
+ ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder());
synchronized (mLock) {
final PermissionManagerServiceInternal permissionManager =
@@ -114,6 +114,8 @@
@GuardedBy("mLock")
private TelecomServiceConnection mServiceConnection;
+ private InternalServiceRepository mServiceRepo;
+
public TelecomLoaderService(Context context) {
super(context);
mContext = context;
@@ -129,6 +131,8 @@
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
registerDefaultAppNotifier();
registerCarrierConfigChangedReceiver();
+ // core services will have already been loaded.
+ setupServiceRepository();
connectToTelecom();
}
}
@@ -154,6 +158,11 @@
}
}
+ private void setupServiceRepository() {
+ DeviceIdleInternal deviceIdleInternal = getLocalService(DeviceIdleInternal.class);
+ mServiceRepo = new InternalServiceRepository(deviceIdleInternal);
+ }
+
private void registerDefaultAppProviders() {
final PermissionManagerServiceInternal permissionManager =
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6df46ed..ad28124 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4628,18 +4628,26 @@
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
}
- /** @return {@code true} if this activity should be made visible. */
- boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
+ private void updateVisibleIgnoringKeyguard(boolean behindFullscreenActivity) {
// Check whether activity should be visible without Keyguard influence
visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
&& okToShowLocked();
+ }
+
+ /** @return {@code true} if this activity should be made visible. */
+ private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
+ updateVisibleIgnoringKeyguard(behindFullscreenActivity);
if (ignoringKeyguard) {
return visibleIgnoringKeyguard;
}
+ return shouldBeVisibleUnchecked();
+ }
+
+ boolean shouldBeVisibleUnchecked() {
final Task stack = getRootTask();
- if (stack == null) {
+ if (stack == null || !visibleIgnoringKeyguard) {
return false;
}
@@ -4652,26 +4660,30 @@
return false;
}
- // Check if the activity is on a sleeping display, and if it can turn it ON.
- if (mDisplayContent.isSleeping()) {
- final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
- || canShowWhenLocked() || containsDismissKeyguardWindow();
- if (!canTurnScreenOn) {
- return false;
- }
+ // Check if the activity is on a sleeping display
+ // TODO b/163993448 mSetToSleep is required when restarting an existing activity, try to
+ // remove it if possible.
+ if (mSetToSleep && mDisplayContent.isSleeping()) {
+ return false;
}
+ return mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
+ }
+
+ void updateVisibility(boolean behindFullscreenActivity) {
+ updateVisibleIgnoringKeyguard(behindFullscreenActivity);
+ final Task task = getRootTask();
+ if (task == null || !visibleIgnoringKeyguard) {
+ return;
+ }
// Now check whether it's really visible depending on Keyguard state, and update
// {@link ActivityStack} internal states.
// Inform the method if this activity is the top activity of this stack, but exclude the
// case where this is the top activity in a pinned stack.
- final boolean isTop = this == stack.getTopNonFinishingActivity();
- final boolean isTopNotPinnedStack = stack.isAttached()
- && stack.getDisplayArea().isTopNotFinishNotPinnedStack(stack);
- final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
- visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
-
- return visibleIgnoringDisplayStatus;
+ final boolean isTop = this == task.getTopNonFinishingActivity();
+ final boolean isTopNotPinnedStack = task.isAttached()
+ && task.getDisplayArea().isTopNotFinishNotPinnedStack(task);
+ task.updateKeyguardVisibility(this, isTop && isTopNotPinnedStack);
}
boolean shouldBeVisible() {
@@ -6643,8 +6655,7 @@
final Configuration resolvedConfig = getResolvedOverrideConfiguration();
final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
final int requestedOrientation = getRequestedConfigurationOrientation();
- final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED
- && !mDisplayContent.ignoreRotationForApps();
+ final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED;
final int orientation = orientationRequested
? requestedOrientation
: newParentConfiguration.orientation;
@@ -7538,10 +7549,8 @@
return false;
}
final Task stack = getRootTask();
- return stack != null
- && !stack.inMultiWindowMode()
- && stack.checkKeyguardVisibility(this, true /* shouldBeVisible */,
- stack.topRunningActivity() == this /* isTop */);
+ return stack != null && !stack.inMultiWindowMode()
+ && mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
}
void setTurnScreenOn(boolean turnScreenOn) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 9df192b7..5196416 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -759,8 +759,7 @@
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
- if (r.getRootTask().checkKeyguardVisibility(r, true /* shouldBeVisible */,
- true /* isTop */) && r.allowMoveToFront()) {
+ if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
// We only set the visibility to true if the activity is not being launched in
// background, and is allowed to be visible based on keyguard state. This avoids
// setting this into motion in window manager that is later cancelled due to later
@@ -2298,11 +2297,15 @@
}
/** Ends a batch of visibility updates. */
- void endActivityVisibilityUpdate() {
- mVisibilityTransactionDepth--;
- if (mVisibilityTransactionDepth == 0) {
+ void endActivityVisibilityUpdate(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ if (mVisibilityTransactionDepth == 1) {
getKeyguardController().visibilitiesUpdated();
+ // commit visibility to activities
+ mRootWindowContainer.commitActivitiesVisible(starting, configChanges, preserveWindows,
+ notifyClients);
}
+ mVisibilityTransactionDepth--;
}
/** Returns {@code true} if the caller is on the path to update visibility. */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 080a438..2657eb2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -137,6 +137,7 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.ActivityThread;
import android.app.AlertDialog;
import android.app.AppGlobals;
@@ -2158,14 +2159,14 @@
}
@Override
- public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getFocusedRootTaskInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
Task focusedStack = getTopDisplayFocusedStack();
if (focusedStack != null) {
- return mRootWindowContainer.getStackInfo(focusedStack.mTaskId);
+ return mRootWindowContainer.getRootTaskInfo(focusedStack.mTaskId);
}
return null;
}
@@ -2893,14 +2894,13 @@
}
}
- // TODO(148895075): deprecate and replace with task equivalents
@Override
- public List<ActivityManager.StackInfo> getAllStackInfos() {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
+ public List<RootTaskInfo> getAllRootTaskInfos() {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllRootTaskInfos()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootWindowContainer.getAllStackInfos(INVALID_DISPLAY);
+ return mRootWindowContainer.getAllRootTaskInfos(INVALID_DISPLAY);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2908,26 +2908,12 @@
}
@Override
- public ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ public RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getRootTaskInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootWindowContainer.getStackInfo(windowingMode, activityType);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- // TODO(148895075): deprecate and replace with task equivalents
- @Override
- public List<ActivityManager.StackInfo> getAllStackInfosOnDisplay(int displayId) {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
- long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- return mRootWindowContainer.getAllStackInfos(displayId);
+ return mRootWindowContainer.getRootTaskInfo(windowingMode, activityType);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2935,13 +2921,27 @@
}
@Override
- public ActivityManager.StackInfo getStackInfoOnDisplay(int windowingMode, int activityType,
+ public List<RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId) {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "getAllRootTaskInfosOnDisplay()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ return mRootWindowContainer.getAllRootTaskInfos(displayId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public RootTaskInfo getRootTaskInfoOnDisplay(int windowingMode, int activityType,
int displayId) {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getRootTaskInfoOnDisplay()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootWindowContainer.getStackInfo(windowingMode, activityType, displayId);
+ return mRootWindowContainer.getRootTaskInfo(windowingMode, activityType, displayId);
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8ccbd11..4db121b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -28,7 +28,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
@@ -36,20 +35,21 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
-import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -367,13 +367,6 @@
final float mCloseToSquareMaxAspectRatio;
/**
- * If this is true, we would not rotate the display for apps. The rotation would be either the
- * sensor rotation or the user rotation, controlled by
- * {@link WindowManagerPolicy.UserRotationMode}.
- */
- private boolean mIgnoreRotationForApps;
-
- /**
* Keep track of wallpaper visibility to notify changes.
*/
private boolean mLastWallpaperVisible = false;
@@ -618,6 +611,12 @@
*/
private boolean mInEnsureActivitiesVisible = false;
+ /**
+ * Last window to be requested focus via {@code SurfaceControl.Transaction#setFocusedWindow} to
+ * prevent duplicate requests to input.
+ */
+ WindowState mLastRequestedFocus = null;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final ActivityRecord activity = w.mActivityRecord;
@@ -1751,26 +1750,6 @@
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
-
- // Not much of use to rotate the display for apps since it's close to square.
- mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
- }
-
- /** @return {@code true} if the orientation requested from application will be ignored. */
- boolean ignoreRotationForApps() {
- return mIgnoreRotationForApps;
- }
-
- private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
- final DisplayCutout displayCutout =
- calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
- final int uiMode = mWmService.mPolicy.getUiMode();
- final int w = mDisplayPolicy.getNonDecorDisplayWidth(
- width, height, rotation, uiMode, displayCutout);
- final int h = mDisplayPolicy.getNonDecorDisplayHeight(
- width, height, rotation, uiMode, displayCutout);
- final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
- return aspectRatio <= mCloseToSquareMaxAspectRatio;
}
/**
@@ -2336,10 +2315,6 @@
int getOrientation() {
mLastOrientationSource = null;
- if (mIgnoreRotationForApps) {
- return SCREEN_ORIENTATION_USER;
- }
-
if (mWmService.mDisplayFrozen) {
if (mWmService.mPolicy.isKeyguardLocked()) {
// Use the last orientation the while the display is frozen with the keyguard
@@ -4753,7 +4728,7 @@
}
// Apply restriction if necessary.
- if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
+ if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) {
// Processes the region along the left edge.
remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
@@ -4770,7 +4745,7 @@
outExclusion.op(middle, Op.UNION);
middle.recycle();
} else {
- boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */);
+ boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */);
if (loggable) {
addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
Integer.MAX_VALUE, w, EXCLUSION_LEFT);
@@ -4792,17 +4767,21 @@
}
/**
- * @return Whether gesture exclusion area should be restricted from the window depending on the
- * current SystemUI visibility flags.
+ * Returns whether gesture exclusion area should be restricted from the window depending on the
+ * window/activity types and the requested navigation bar visibility and the behavior.
+ *
+ * @param win The target window.
+ * @param ignoreRequest If this is {@code true}, only the window/activity types are considered.
+ * @return {@code true} if the gesture exclusion restrictions are needed.
*/
- private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
+ private static boolean needsGestureExclusionRestrictions(WindowState win,
+ boolean ignoreRequest) {
final int type = win.mAttrs.type;
- final int stickyHideNavFlags =
- SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
final boolean stickyHideNav =
- (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
- return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_NOTIFICATION_SHADE
- && win.getActivityType() != ACTIVITY_TYPE_HOME;
+ !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+ return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
+ && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
}
/**
@@ -4818,7 +4797,7 @@
&& type != TYPE_APPLICATION_STARTING
&& type != TYPE_NAVIGATION_BAR
&& (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
- && needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */)
+ && needsGestureExclusionRestrictions(win, true /* ignoreRequest */)
&& win.getDisplayContent().mDisplayPolicy.hasSideGestures();
}
@@ -5293,6 +5272,14 @@
mSingleTaskInstance = true;
}
+ /**
+ * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
+ */
+ boolean canShowWithInsecureKeyguard() {
+ final int flags = mDisplay.getFlags();
+ return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
+ }
+
/** Returns true if the display can only contain one task */
boolean isSingleTaskInstance() {
return mSingleTaskInstance;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c9f463b..6e32d0e 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -308,7 +308,7 @@
}
void tearDown() {
- mService.mInputManager.unregisterInputChannel(mServerChannel);
+ mService.mInputManager.unregisterInputChannel(mServerChannel.getToken());
mInputEventReceiver.dispose();
mInputEventReceiver = null;
mClientChannel.dispose();
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 5a24847..8d20bb8 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -192,7 +192,7 @@
void onRemoved() {
if (mInputChannel != null) {
- mWmService.mInputManager.unregisterInputChannel(mInputChannel);
+ mWmService.mInputManager.unregisterInputChannel(mInputChannel.getToken());
mInputChannel.dispose();
mInputChannel = null;
}
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index e2c0749..251c014 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -22,12 +22,9 @@
import android.annotation.Nullable;
import android.util.Slog;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
-
/** Helper class to ensure activities are in the right visible state for a container. */
class EnsureActivitiesVisibleHelper {
- private final Task mContiner;
+ private final Task mTask;
private ActivityRecord mTop;
private ActivityRecord mStarting;
private boolean mAboveTop;
@@ -38,11 +35,11 @@
private boolean mNotifyClients;
EnsureActivitiesVisibleHelper(Task container) {
- mContiner = container;
+ mTask = container;
}
/**
- * Update all attributes except {@link mContiner} to use in subsequent calculations.
+ * Update all attributes except {@link mTask} to use in subsequent calculations.
*
* @param starting The activity that is being started
* @param configChanges Parts of the configuration that changed for this activity for evaluating
@@ -54,11 +51,11 @@
void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
boolean notifyClients) {
mStarting = starting;
- mTop = mContiner.topRunningActivity();
+ mTop = mTask.topRunningActivity();
// If the top activity is not fullscreen, then we need to make sure any activities under it
// are now visible.
mAboveTop = mTop != null;
- mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting);
+ mContainerShouldBeVisible = mTask.shouldBeVisible(mStarting);
mBehindFullscreenActivity = !mContainerShouldBeVisible;
mConfigChanges = configChanges;
mPreserveWindows = preserveWindows;
@@ -66,7 +63,26 @@
}
/**
- * Ensure visibility with an option to also update the configuration of visible activities.
+ * Update visibility to activities.
+ * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @param starting The top most activity in the task.
+ * The activity is either starting or resuming.
+ * Caller should ensure starting activity is visible.
+ *
+ */
+ void processUpdate(@Nullable ActivityRecord starting) {
+ reset(starting, 0 /* configChanges */, false /* preserveWindows */,
+ false /* notifyClients */);
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processUpdate behind " + mTop);
+ }
+
+ mTask.forAllActivities(this::updateActivityVisibility);
+ }
+
+ /**
+ * Commit visibility with an option to also update the configuration of visible activities.
* @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
* @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
* @param starting The top most activity in the task.
@@ -79,54 +95,84 @@
* @param notifyClients Flag indicating whether the configuration and visibility changes shoulc
* be sent to the clients.
*/
- void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
- boolean notifyClients) {
+ void processCommit(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
reset(starting, configChanges, preserveWindows, notifyClients);
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop
- + " configChanges=0x" + Integer.toHexString(configChanges));
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processCommit behind " + mTop);
+ }
if (mTop != null) {
- mContiner.checkTranslucentActivityWaiting(mTop);
+ mTask.checkTranslucentActivityWaiting(mTop);
}
// We should not resume activities that being launched behind because these
// activities are actually behind other fullscreen activities, but still required
// to be visible (such as performing Recents animation).
final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
- && mContiner.isTopActivityFocusable()
- && (starting == null || !starting.isDescendantOf(mContiner));
+ && mTask.isTopActivityFocusable()
+ && (starting == null || !starting.isDescendantOf(mTask));
- final PooledConsumer f = PooledLambda.obtainConsumer(
- EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
- PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity);
- mContiner.forAllActivities(f);
- f.recycle();
+ mTask.forAllActivities(a -> {
+ commitActivityVisibility(a, starting, resumeTopActivity);
+ });
}
- private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
- final boolean resumeTopActivity) {
- final boolean isTop = r == mTop;
+ private boolean isAboveTop(boolean isTop) {
if (mAboveTop && !isTop) {
- return;
+ return true;
}
mAboveTop = false;
+ return false;
+ }
- final boolean reallyVisible = r.shouldBeVisible(
- mBehindFullscreenActivity, false /* ignoringKeyguard */);
+ private void updateActivityVisibility(ActivityRecord r) {
+ final boolean isTop = r == mTop;
+ if (isAboveTop(isTop)) {
+ return;
+ }
+
+ r.updateVisibility(mBehindFullscreenActivity);
// Check whether activity should be visible without Keyguard influence
if (r.visibleIgnoringKeyguard) {
if (r.occludesParent()) {
// At this point, nothing else needs to be shown in this task.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
- + " stackVisible=" + mContainerShouldBeVisible
- + " behindFullscreen=" + mBehindFullscreenActivity);
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
+ + " stackVisible=" + mContainerShouldBeVisible
+ + " behindFullscreen=" + mBehindFullscreenActivity);
+ }
mBehindFullscreenActivity = true;
} else {
mBehindFullscreenActivity = false;
}
}
+ if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) {
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_VISIBILITY, "Home task: at " + mTask
+ + " stackShouldBeVisible=" + mContainerShouldBeVisible
+ + " behindFullscreenActivity=" + mBehindFullscreenActivity);
+ }
+ // No other task in the home stack should be visible behind the home activity.
+ // Home activities is usually a translucent activity with the wallpaper behind
+ // them. However, when they don't have the wallpaper behind them, we want to
+ // show activities in the next application stack behind them vs. another
+ // task in the home stack like recents.
+ mBehindFullscreenActivity = true;
+ }
+ }
+
+ private void commitActivityVisibility(ActivityRecord r, ActivityRecord starting,
+ final boolean resumeTopActivity) {
+ final boolean isTop = r == mTop;
+ if (isAboveTop(isTop)) {
+ return;
+ }
+
+ final boolean reallyVisible = r.shouldBeVisibleUnchecked();
+
if (reallyVisible) {
if (r.finishing) {
return;
@@ -170,20 +216,6 @@
+ " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
r.makeInvisible();
}
-
- final int windowingMode = mContiner.getWindowingMode();
- if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome()
- && r.isRootOfTask()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
- + " stackShouldBeVisible=" + mContainerShouldBeVisible
- + " behindFullscreenActivity=" + mBehindFullscreenActivity);
- // No other task in the home stack should be visible behind the home activity.
- // Home activities is usually a translucent activity with the wallpaper behind
- // them. However, when they don't have the wallpaper behind them, we want to
- // show activities in the next application stack behind them vs. another
- // task in the home stack like recents.
- mBehindFullscreenActivity = true;
- }
}
private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
@@ -207,7 +239,7 @@
r.setVisibility(true);
}
if (r != starting) {
- mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
+ mTask.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
}
}
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index a79d3bb..1d1a266 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -156,7 +156,7 @@
}
void disposeChannelsLw(SurfaceControl.Transaction t) {
- mService.mInputManager.unregisterInputChannel(mServerChannel);
+ mService.mInputManager.unregisterInputChannel(mServerChannel.getToken());
mClientChannel.dispose();
mServerChannel.dispose();
t.remove(mInputSurface);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4efd687..714591a 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
@@ -275,7 +276,7 @@
void populateInputWindowHandle(final InputWindowHandle inputWindowHandle,
final WindowState child, int flags, final int type, final boolean isVisible,
- final boolean hasFocus, final boolean hasWallpaper) {
+ final boolean focusable, final boolean hasWallpaper) {
// Add a window to our list of input windows.
inputWindowHandle.name = child.toString();
flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags);
@@ -283,7 +284,7 @@
inputWindowHandle.layoutParamsType = type;
inputWindowHandle.dispatchingTimeoutMillis = child.getInputDispatchingTimeoutMillis();
inputWindowHandle.visible = isVisible;
- inputWindowHandle.focusable = hasFocus;
+ inputWindowHandle.focusable = focusable;
inputWindowHandle.hasWallpaper = hasWallpaper;
inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
inputWindowHandle.ownerPid = child.mSession.mPid;
@@ -308,10 +309,13 @@
* This means we need to make sure that these changes in crop are reflected
* in the input windows, and so ensure this flag is set so that
* the input crop always reflects the surface hierarchy.
- * we may have some issues with modal-windows, but I guess we can
- * cross that bridge when we come to implementing full-screen TaskOrg
+ *
+ * TODO(b/168252846): we have some issues with modal-windows, so we need to
+ * cross that bridge now that we organize full-screen Tasks.
*/
- if (child.getTask() != null && child.getTask().isOrganized()) {
+ if (child.getTask() != null
+ && child.getTask().isOrganized()
+ && child.getTask().getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */);
}
@@ -472,8 +476,9 @@
resetInputConsumers(mInputTransaction);
- mDisplayContent.forAllWindows(this,
- true /* traverseTopToBottom */);
+ mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);
+
+ updateInputFocusRequest();
if (!mUpdateInputWindowsImmediately) {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
@@ -483,6 +488,29 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ private void updateInputFocusRequest() {
+ if (mDisplayContent.mLastRequestedFocus == mDisplayContent.mCurrentFocus) {
+ return;
+ }
+
+ final WindowState focus = mDisplayContent.mCurrentFocus;
+ if (focus == null || focus.mInputWindowHandle.token == null) {
+ mDisplayContent.mLastRequestedFocus = focus;
+ return;
+ }
+
+ if (!focus.mWinAnimator.hasSurface()) {
+ ProtoLog.d(WM_DEBUG_FOCUS_LIGHT,
+ "Focus not requested for window=%s because it has no surface",
+ focus);
+ return;
+ }
+
+ mInputTransaction.setFocusedWindow(focus.mInputWindowHandle.token, mDisplayId);
+ mDisplayContent.mLastRequestedFocus = focus;
+ ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Focus requested for window=%s", focus);
+ }
+
@Override
public void accept(WindowState w) {
final InputChannel inputChannel = w.mInputChannel;
@@ -510,11 +538,12 @@
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
- final boolean hasFocus = w.isFocused();
+ final boolean focusable = w.canReceiveKeys()
+ && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
- mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
+ mRecentsAnimationInputConsumer.mWindowHandle, focusable)) {
mRecentsAnimationInputConsumer.show(mInputTransaction, w);
mAddRecentsAnimationInputConsumerHandle = false;
}
@@ -559,7 +588,7 @@
}
populateInputWindowHandle(
- inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
+ inputWindowHandle, w, flags, type, isVisible, focusable, hasWallpaper);
// register key interception info
mService.mKeyInterceptionInfoForToken.put(inputWindowHandle.token,
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index ab1074e..5520ad3 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -286,6 +286,7 @@
}
if (changed) {
notifyInsetsChanged();
+ mDisplayContent.updateSystemGestureExclusion();
mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw();
}
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 69e8c57..bad28ba 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -278,6 +278,27 @@
}
/**
+ * Checks whether {@param r} should be visible depending on Keyguard state.
+ *
+ * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
+ */
+ boolean checkKeyguardVisibility(ActivityRecord r) {
+ if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) {
+ return true;
+ }
+
+ if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) {
+ // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
+ // right away and AOD isn't visible.
+ return canShowActivityWhileKeyguardShowing(r, r.containsDismissKeyguardWindow());
+ } else if (isKeyguardLocked()) {
+ return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked());
+ } else {
+ return true;
+ }
+ }
+
+ /**
* Makes sure to update lockscreen occluded/dismiss state if needed after completing all
* visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}).
*/
@@ -442,6 +463,7 @@
private final int mDisplayId;
private boolean mOccluded;
private ActivityRecord mDismissingKeyguardActivity;
+ private ActivityRecord mTopTurnScreenOnActivity;
private boolean mRequestDismissKeyguard;
private final ActivityTaskManagerService mService;
private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
@@ -455,30 +477,38 @@
void onRemoved() {
mDismissingKeyguardActivity = null;
+ mTopTurnScreenOnActivity = null;
mSleepTokenAcquirer.release(mDisplayId);
}
void visibilitiesUpdated(KeyguardController controller, DisplayContent display) {
final boolean lastOccluded = mOccluded;
final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
+ final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity;
mRequestDismissKeyguard = false;
mOccluded = false;
mDismissingKeyguardActivity = null;
+ mTopTurnScreenOnActivity = null;
+ // only top + focusable + visible task can control occluding.
final Task stack = getStackForControllingOccluding(display);
if (stack != null) {
final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
+ final ActivityRecord topTurnScreenOn = stack.getTopTurnScreenOnActivity();
mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
&& stack.topRunningActivity() == topDismissing
&& controller.canShowWhileOccluded(
true /* dismissKeyguard */,
false /* showWhenLocked */));
- if (stack.getTopDismissingKeyguardActivity() != null) {
- mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
+ if (topDismissing != null) {
+ mDismissingKeyguardActivity = topDismissing;
+ }
+ if (topTurnScreenOn != null) {
+ mTopTurnScreenOnActivity = topTurnScreenOn;
}
// FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
- if (mDisplayId != DEFAULT_DISPLAY) {
- mOccluded |= stack.canShowWithInsecureKeyguard()
+ if (mDisplayId != DEFAULT_DISPLAY && stack.mDisplayContent != null) {
+ mOccluded |= stack.mDisplayContent.canShowWithInsecureKeyguard()
&& controller.canDismissKeyguard();
}
}
@@ -488,14 +518,20 @@
.getDisplayPolicy().isShowingDreamLw();
}
- if (lastOccluded != mOccluded) {
- controller.handleOccludedChanged(mDisplayId);
- }
- if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
+ mRequestDismissKeyguard = lastDismissActivity != mDismissingKeyguardActivity
+ && !mOccluded
&& mDismissingKeyguardActivity != null
&& controller.mWindowManager.isKeyguardSecure(
- controller.mService.getCurrentUserId())) {
- mRequestDismissKeyguard = true;
+ controller.mService.getCurrentUserId());
+
+ if (mTopTurnScreenOnActivity != null
+ && mTopTurnScreenOnActivity != lastTurnScreenOnActivity
+ && !mService.mWindowManager.mPowerManager.isInteractive()) {
+ controller.mStackSupervisor.wakeUp("handleTurnScreenOn");
+ }
+
+ if (lastOccluded != mOccluded) {
+ controller.handleOccludedChanged(mDisplayId);
}
}
@@ -525,6 +561,8 @@
sb.append(" Occluded=").append(mOccluded)
.append(" DismissingKeyguardActivity=")
.append(mDismissingKeyguardActivity)
+ .append(" TurnScreenOnActivity=")
+ .append(mTopTurnScreenOnActivity)
.append(" at display=")
.append(mDisplayId);
pw.println(sb.toString());
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index dccd3a6..4fe678d 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -239,7 +239,7 @@
}
void dispose() {
- mWmService.mInputManager.unregisterInputChannel(mServerChannel);
+ mWmService.mInputManager.unregisterInputChannel(mServerChannel.getToken());
mInputEventReceiver.dispose();
mServerChannel.dispose();
mClientChannel.dispose();
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6882dc4..b50cb4c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -814,14 +814,14 @@
}
boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
- boolean hasFocus) {
+ boolean focusable) {
// Update the input consumer touchable region to match the target app main window
final WindowState targetAppMainWindow = mTargetActivityRecord != null
? mTargetActivityRecord.findMainWindow()
: null;
if (targetAppMainWindow != null) {
targetAppMainWindow.getBounds(mTmpRect);
- inputWindowHandle.focusable = hasFocus;
+ inputWindowHandle.focusable = focusable;
inputWindowHandle.touchableRegion.set(mTmpRect);
return true;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6539e13..d149db6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -99,6 +99,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AppGlobals;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -1982,10 +1983,22 @@
notifyClients);
}
} finally {
- mStackSupervisor.endActivityVisibilityUpdate();
+ mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows,
+ notifyClients);
}
}
+ void commitActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ forAllTaskDisplayAreas(taskDisplayArea -> {
+ for (int stackNdx = taskDisplayArea.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final Task task = taskDisplayArea.getStackAt(stackNdx);
+ task.commitActivitiesVisible(starting, configChanges, preserveWindows,
+ notifyClients);
+ }
+ });
+ }
+
boolean switchUser(int userId, UserState uss) {
final Task topFocusedStack = getTopDisplayFocusedStack();
final int focusStackId = topFocusedStack != null
@@ -2201,7 +2214,22 @@
ensureActivitiesVisible(null, 0, false /* preserveWindows */);
resumeFocusedStacksTopActivities();
- mService.getTaskChangeNotificationController().notifyActivityPinned(r);
+ notifyActivityPipModeChanged(r);
+ }
+
+ /**
+ * Notifies when an activity enters or leaves PIP mode.
+ * @param r indicates the activity currently in PIP, can be null to indicate no activity is
+ * currently in PIP mode.
+ */
+ void notifyActivityPipModeChanged(@Nullable ActivityRecord r) {
+ final boolean inPip = r != null;
+ if (inPip) {
+ mService.getTaskChangeNotificationController().notifyActivityPinned(r);
+ } else {
+ mService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ }
+ mWindowManager.mPolicy.setPipVisibilityLw(inPip);
}
void executeAppTransitionForAllDisplay() {
@@ -2423,77 +2451,73 @@
return display.getStack(windowingMode, activityType);
}
- private ActivityManager.StackInfo getStackInfo(Task stack) {
- final TaskDisplayArea taskDisplayArea = stack.getDisplayArea();
- ActivityManager.StackInfo info = new ActivityManager.StackInfo();
- stack.getBounds(info.bounds);
- info.displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId() : INVALID_DISPLAY;
- info.stackId = stack.mTaskId;
- info.stackToken = stack.mRemoteToken.toWindowContainerToken();
- info.userId = stack.mCurrentUser;
- info.visible = stack.shouldBeVisible(null);
- // A stack might be not attached to a display.
- // TODO: Can be removed since no one is using it.
- info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(stack) : 0;
- info.configuration.setTo(stack.getConfiguration());
+ private RootTaskInfo getRootTaskInfo(Task task) {
+ final TaskDisplayArea taskDisplayArea = task.getDisplayArea();
+ RootTaskInfo info = new RootTaskInfo();
+ task.fillTaskInfo(info);
- final int numTasks = stack.getDescendantTaskCount();
- info.taskIds = new int[numTasks];
- info.taskNames = new String[numTasks];
- info.taskBounds = new Rect[numTasks];
- info.taskUserIds = new int[numTasks];
+ // A task might be not attached to a display.
+ info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(task) : 0;
+ info.visible = task.shouldBeVisible(null);
+ task.getBounds(info.bounds);
+
+ final int numTasks = task.getDescendantTaskCount();
+ info.childTaskIds = new int[numTasks];
+ info.childTaskNames = new String[numTasks];
+ info.childTaskBounds = new Rect[numTasks];
+ info.childTaskUserIds = new int[numTasks];
final int[] currentIndex = {0};
final PooledConsumer c = PooledLambda.obtainConsumer(
- RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
+ RootWindowContainer::processTaskForTaskInfo, PooledLambda.__(Task.class), info,
currentIndex);
- stack.forAllLeafTasks(c, false /* traverseTopToBottom */);
+ task.forAllLeafTasks(c, false /* traverseTopToBottom */);
c.recycle();
- final ActivityRecord top = stack.topRunningActivity();
+ final ActivityRecord top = task.topRunningActivity();
info.topActivity = top != null ? top.intent.getComponent() : null;
return info;
}
- private static void processTaskForStackInfo(
- Task task, ActivityManager.StackInfo info, int[] currentIndex) {
+ private static void processTaskForTaskInfo(
+ Task task, RootTaskInfo info, int[] currentIndex) {
int i = currentIndex[0];
- info.taskIds[i] = task.mTaskId;
- info.taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
+ info.childTaskIds[i] = task.mTaskId;
+ info.childTaskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
: task.realActivity != null ? task.realActivity.flattenToString()
: task.getTopNonFinishingActivity() != null
? task.getTopNonFinishingActivity().packageName : "unknown";
- info.taskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId);
- info.taskUserIds[i] = task.mUserId;
+ info.childTaskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId);
+ info.childTaskUserIds[i] = task.mUserId;
currentIndex[0] = ++i;
}
- ActivityManager.StackInfo getStackInfo(int stackId) {
- Task stack = getStack(stackId);
- if (stack != null) {
- return getStackInfo(stack);
+ RootTaskInfo getRootTaskInfo(int taskId) {
+ Task task = getStack(taskId);
+ if (task != null) {
+ return getRootTaskInfo(task);
}
return null;
}
- ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
+ RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
final Task stack = getStack(windowingMode, activityType);
- return (stack != null) ? getStackInfo(stack) : null;
+ return (stack != null) ? getRootTaskInfo(stack) : null;
}
- ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType, int displayId) {
+ RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) {
final Task stack = getStack(windowingMode, activityType, displayId);
- return (stack != null) ? getStackInfo(stack) : null;
+ return (stack != null) ? getRootTaskInfo(stack) : null;
}
- /** If displayId == INVALID_DISPLAY, this will get stack infos on all displays */
- ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) {
- ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
+ /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */
+ ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) {
+ ArrayList<RootTaskInfo> list = new ArrayList<>();
if (displayId == INVALID_DISPLAY) {
forAllTaskDisplayAreas(taskDisplayArea -> {
for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
final Task stack = taskDisplayArea.getStackAt(sNdx);
- list.add(getStackInfo(stack));
+ list.add(getRootTaskInfo(stack));
}
});
return list;
@@ -2505,7 +2529,7 @@
display.forAllTaskDisplayAreas(taskDisplayArea -> {
for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
final Task stack = taskDisplayArea.getStackAt(sNdx);
- list.add(getStackInfo(stack));
+ list.add(getRootTaskInfo(stack));
}
});
return list;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 3b32a9d76..3d6d7b7 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -56,6 +56,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowManager;
+import android.window.ClientWindowFrames;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.protolog.common.ProtoLog;
@@ -201,9 +202,7 @@
@Override
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
- Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
- Rect outStableInsets, Rect outBackdropFrame,
- DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
+ ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
SurfaceControl outBLASTSurfaceControl) {
@@ -212,10 +211,8 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
- outFrame, outContentInsets, outVisibleInsets,
- outStableInsets, outBackdropFrame, cutout,
- mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls,
- outSurfaceSize, outBLASTSurfaceControl);
+ outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
+ outActiveControls, outSurfaceSize, outBLASTSurfaceControl);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
@@ -240,11 +237,6 @@
}
@Override
- public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
- mService.getWindowDisplayFrame(this, window, outDisplayFrame);
- }
-
- @Override
public void finishDrawing(IWindow window,
@Nullable SurfaceControl.Transaction postDrawTransaction) {
if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c35d732..15a44e8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -61,7 +61,6 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
@@ -197,7 +196,6 @@
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import android.view.Display;
import android.view.DisplayInfo;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
@@ -600,6 +598,7 @@
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
+ private ActivityRecord mTopTurnScreenOnActivity;
private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1;
@@ -1394,7 +1393,8 @@
}
if (display != null) {
- // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
+ // TODO(b/168037178): Chat with the erosky@ of this code to see if this really makes
+ // sense here...
// Rotations are relative to the display. This means if there are 2 displays rotated
// differently (eg. 2 monitors with one landscape and one portrait), moving a stack
// from one to the other could look like a rotation change. To prevent this
@@ -1408,11 +1408,16 @@
super.onParentChanged(newParent, oldParent);
- // TODO(NOW): The check for null display content and setting it to null doesn't really
- // make sense here...
+ // Call this again after super onParentChanged in-case the surface wasn't created yet
+ // (happens when the task is first inserted into the hierarchy). It's a no-op if it
+ // already ran fully within super.onParentChanged
+ updateTaskOrganizerState(false /* forceUpdate */);
- // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
- // the display, so we should probably consolidate it there instead.
+ // TODO(b/168037178): The check for null display content and setting it to null doesn't
+ // really make sense here...
+
+ // TODO(b/168037178): This is mostly taking care of the case where the stask is removing
+ // from the display, so we should probably consolidate it there instead.
if (getParent() == null && mDisplayContent != null) {
EventLogTags.writeWmStackRemoved(getRootTaskId());
@@ -1434,7 +1439,7 @@
&& (newParent == null || !newParent.inPinnedWindowingMode())) {
// Notify if a task from the pinned stack is being removed
// (or moved depending on the mode).
- mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ mRootWindowContainer.notifyActivityPipModeChanged(null);
}
}
@@ -4019,7 +4024,7 @@
*/
void fillTaskInfo(TaskInfo info, boolean stripExtras) {
getNumRunningActivities(mReuseActivitiesReport);
- info.userId = mUserId;
+ info.userId = isLeafTask() ? mUserId : mCurrentUser;
info.stackId = getRootTaskId();
info.taskId = mTaskId;
info.displayId = getDisplayId();
@@ -4850,6 +4855,11 @@
* @return {@code true} if task organizer changed.
*/
boolean updateTaskOrganizerState(boolean forceUpdate) {
+ if (getSurfaceControl() == null) {
+ // Can't call onTaskAppeared without a surfacecontrol, so defer this until after one
+ // is created.
+ return false;
+ }
if (!isRootTask()) {
return setTaskOrganizer(null);
}
@@ -5102,10 +5112,11 @@
: WINDOWING_MODE_FULLSCREEN;
}
if (currentMode == WINDOWING_MODE_PINNED) {
- mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ mRootWindowContainer.notifyActivityPipModeChanged(null);
}
if (likelyResolvedMode == WINDOWING_MODE_PINNED
&& taskDisplayArea.getRootPinnedTask() != null) {
+
// Can only have 1 pip at a time, so replace an existing pip
taskDisplayArea.getRootPinnedTask().dismissPip();
}
@@ -5663,21 +5674,29 @@
boolean preserveWindows, boolean notifyClients) {
mTopActivityOccludesKeyguard = false;
mTopDismissingKeyguardActivity = null;
+ mTopTurnScreenOnActivity = null;
mStackSupervisor.beginActivityVisibilityUpdate();
try {
- mEnsureActivitiesVisibleHelper.process(
- starting, configChanges, preserveWindows, notifyClients);
+ mEnsureActivitiesVisibleHelper.processUpdate(starting);
if (mTranslucentActivityWaiting != null &&
mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
- // Nothing is getting drawn or everything was already visible, don't wait for timeout.
+ // Nothing is getting drawn or everything was already visible, don't wait for
+ // timeout.
notifyActivityDrawnLocked(null);
}
} finally {
- mStackSupervisor.endActivityVisibilityUpdate();
+ mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows,
+ notifyClients);
}
}
+ void commitActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ mEnsureActivitiesVisibleHelper.processCommit(starting, configChanges, preserveWindows,
+ notifyClients);
+ }
+
/**
* @return true if the top visible activity wants to occlude the Keyguard, false otherwise
*/
@@ -5711,64 +5730,34 @@
}
/**
- * Checks whether {@param r} should be visible depending on Keyguard state and updates
- * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if
- * necessary.
- *
- * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
+ * @return the top most visible activity that wants to turn screen on
*/
- boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) {
- int displayId = getDisplayId();
- if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
-
- final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController()
- .isKeyguardOrAodShowing(displayId);
- final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
- final boolean showWhenLocked = r.canShowWhenLocked();
- final boolean dismissKeyguard = r.containsDismissKeyguardWindow();
- if (shouldBeVisible) {
- if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
- mTopDismissingKeyguardActivity = r;
- }
-
- // Only the top activity may control occluded, as we can't occlude the Keyguard if the
- // top app doesn't want to occlude it.
- if (isTop) {
- mTopActivityOccludesKeyguard |= showWhenLocked;
- }
-
- final boolean canShowWithKeyguard = canShowWithInsecureKeyguard()
- && mStackSupervisor.getKeyguardController().canDismissKeyguard();
- if (canShowWithKeyguard) {
- return true;
- }
- }
- if (keyguardOrAodShowing) {
- // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
- // right away and AOD isn't visible.
- return shouldBeVisible && mStackSupervisor.getKeyguardController()
- .canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
- } else if (keyguardLocked) {
- return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded(
- dismissKeyguard, showWhenLocked);
- } else {
- return shouldBeVisible;
- }
+ ActivityRecord getTopTurnScreenOnActivity() {
+ return mTopTurnScreenOnActivity;
}
/**
- * Check if the display to which this stack is attached has
- * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
+ * Updates {@link #mTopActivityOccludesKeyguard}, {@link #mTopTurnScreenOnActivity} and
+ * {@link #mTopDismissingKeyguardActivity} if this task could be visible.
+ *
*/
- boolean canShowWithInsecureKeyguard() {
- final DisplayContent displayContent = mDisplayContent;
- if (displayContent == null) {
- throw new IllegalStateException("Stack is not attached to any display, stackId="
- + getRootTaskId());
+ void updateKeyguardVisibility(ActivityRecord r, boolean isTop) {
+ final boolean showWhenLocked = r.canShowWhenLocked();
+ final boolean dismissKeyguard = r.containsDismissKeyguardWindow();
+ final boolean turnScreenOn = r.canTurnScreenOn();
+ if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
+ mTopDismissingKeyguardActivity = r;
}
- final int flags = displayContent.mDisplay.getFlags();
- return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
+ if (turnScreenOn && mTopTurnScreenOnActivity == null) {
+ mTopTurnScreenOnActivity = r;
+ }
+
+ // Only the top activity may control occluded, as we can't occlude the Keyguard if the
+ // top app doesn't want to occlude it.
+ if (isTop) {
+ mTopActivityOccludesKeyguard |= showWhenLocked;
+ }
}
void checkTranslucentActivityWaiting(ActivityRecord top) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 6550167..2b32e40 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1779,7 +1779,8 @@
notifyClients);
}
} finally {
- mAtmService.mStackSupervisor.endActivityVisibilityUpdate();
+ mAtmService.mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges,
+ preserveWindows, notifyClients);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index d9290fb..e07c567 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -18,10 +18,8 @@
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
@@ -73,11 +71,9 @@
// The set of modes that are currently supports
// TODO: Remove once the task organizer can support all modes
@VisibleForTesting
- static final int[] SUPPORTED_WINDOWING_MODES = {
- WINDOWING_MODE_PINNED,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
- WINDOWING_MODE_MULTI_WINDOW,
+ static final int[] UNSUPPORTED_WINDOWING_MODES = {
+ WINDOWING_MODE_UNDEFINED,
+ WINDOWING_MODE_FREEFORM
};
private final WindowManagerGlobalLock mGlobalLock;
@@ -311,18 +307,17 @@
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d",
organizer.asBinder(), uid);
- for (int winMode : SUPPORTED_WINDOWING_MODES) {
- if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
- mTaskOrganizers.add(organizer);
- mTaskOrganizerStates.put(organizer.asBinder(),
- new TaskOrganizerState(organizer, uid));
- }
- mService.mRootWindowContainer.forAllTasks((task) -> {
- if (task.getWindowingMode() == winMode) {
- task.updateTaskOrganizerState(true /* forceUpdate */);
- }
- });
+ if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
+ mTaskOrganizers.add(organizer);
+ mTaskOrganizerStates.put(organizer.asBinder(),
+ new TaskOrganizerState(organizer, uid));
}
+ mService.mRootWindowContainer.forAllTasks((task) -> {
+ if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, task.getWindowingMode())) {
+ return;
+ }
+ task.updateTaskOrganizerState(true /* forceUpdate */);
+ });
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -360,12 +355,7 @@
}
private boolean isSupportedWindowingMode(int winMode) {
- for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) {
- if (SUPPORTED_WINDOWING_MODES[i] == winMode) {
- return true;
- }
- }
- return false;
+ return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode);
}
void onTaskAppeared(ITaskOrganizer organizer, Task task) {
@@ -659,21 +649,18 @@
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.print(prefix); pw.println("TaskOrganizerController:");
- pw.print(innerPrefix); pw.println("Per windowing mode:");
- for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) {
- final int windowingMode = SUPPORTED_WINDOWING_MODES[i];
- pw.println(innerPrefix + " "
- + WindowConfiguration.windowingModeToString(windowingMode) + ":");
- for (final TaskOrganizerState state : mTaskOrganizerStates.values()) {
- final ArrayList<Task> tasks = state.mOrganizedTasks;
- pw.print(innerPrefix + " ");
- pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
- for (int k = 0; k < tasks.size(); k++) {
- final Task task = tasks.get(k);
- if (windowingMode == task.getWindowingMode()) {
- pw.println(innerPrefix + " " + task);
- }
+ for (final TaskOrganizerState state : mTaskOrganizerStates.values()) {
+ final ArrayList<Task> tasks = state.mOrganizedTasks;
+ pw.print(innerPrefix + " ");
+ pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
+ for (int k = 0; k < tasks.size(); k++) {
+ final Task task = tasks.get(k);
+ final int mode = task.getWindowingMode();
+ if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, mode)) {
+ continue;
}
+ pw.println(innerPrefix + " ("
+ + WindowConfiguration.windowingModeToString(mode) + ") " + task);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f32781a..abe6329 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -299,7 +299,7 @@
}
mService.mTaskPositioningController.hideInputSurface(mDisplayContent.getDisplayId());
- mService.mInputManager.unregisterInputChannel(mServerChannel);
+ mService.mInputManager.unregisterInputChannel(mServerChannel.getToken());
mInputEventReceiver.dispose();
mInputEventReceiver = null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index e9ada6b..100f1bf 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -67,7 +67,6 @@
import android.os.SystemClock;
import android.util.MergedConfiguration;
import android.util.Slog;
-import android.view.DisplayCutout;
import android.view.IWindowSession;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -79,6 +78,7 @@
import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.window.ClientWindowFrames;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -159,12 +159,8 @@
final IWindowSession session = WindowManagerGlobal.getWindowSession();
window.setSession(session);
final SurfaceControl surfaceControl = new SurfaceControl();
- final Rect tmpRect = new Rect();
- final DisplayCutout.ParcelableWrapper tmpCutout = new DisplayCutout.ParcelableWrapper();
- final Rect tmpFrame = new Rect();
+ final ClientWindowFrames tmpFrames = new ClientWindowFrames();
final Rect taskBounds;
- final Rect tmpContentInsets = new Rect();
- final Rect tmpStableInsets = new Rect();
final InsetsState mTmpInsetsState = new InsetsState();
final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
@@ -254,8 +250,9 @@
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
- View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect,
- tmpRect, tmpCutout, null, mTmpInsetsState, mTempControls);
+ View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrames.frame,
+ tmpFrames.contentInsets, tmpFrames.stableInsets, tmpFrames.displayCutout,
+ null /* outInputChannel */, mTmpInsetsState, mTempControls);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
return null;
@@ -270,15 +267,14 @@
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
- tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect,
- tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
+ tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
mTempControls, sTmpSurfaceSize, sTmpSurfaceControl);
} catch (RemoteException e) {
// Local call.
}
- final Rect systemBarInsets = getSystemBarInsets(tmpFrame, insetsState);
- snapshotSurface.setFrames(tmpFrame, systemBarInsets);
+ final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, insetsState);
+ snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets);
snapshotSurface.drawSnapshot();
return snapshotSurface;
}
@@ -528,11 +524,9 @@
}
@Override
- public void resized(Rect frame, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, boolean reportDraw,
- MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
if (mergedConfiguration != null && mOuter != null
&& mOuter.mOrientationOnCreation
!= mergedConfiguration.getMergedConfiguration().orientation) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 8a5e70f..ae8f7a5 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -2464,8 +2465,9 @@
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) {
- if (isOrganized()) {
- // Defer to the task organizer to run animations
+ if (isOrganized()
+ // TODO(b/161711458): Clean-up when moved to shell.
+ && getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
return null;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 017747f..8eb6432 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -258,6 +258,7 @@
import android.view.WindowManager.TransitionType;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
+import android.window.ClientWindowFrames;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -2065,21 +2066,6 @@
}
}
- public void getWindowDisplayFrame(Session session, IWindow client,
- Rect outDisplayFrame) {
- synchronized (mGlobalLock) {
- WindowState win = windowForClientLocked(session, client, false);
- if (win == null) {
- outDisplayFrame.setEmpty();
- return;
- }
- outDisplayFrame.set(win.getDisplayFrame());
- if (win.inSizeCompatMode()) {
- outDisplayFrame.scale(win.mInvGlobalScale);
- }
- }
- }
-
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
synchronized (mGlobalLock) {
if (mAccessibilityController != null) {
@@ -2115,9 +2101,7 @@
public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
- long frameNumber, Rect outFrame, Rect outContentInsets,
- Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame,
- DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
+ long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
SurfaceControl outBLASTSurfaceControl) {
@@ -2386,10 +2370,6 @@
if (win.mActivityRecord != null) {
win.mActivityRecord.updateReportedVisibilityLocked();
}
- if (winAnimator.mReportSurfaceResized) {
- winAnimator.mReportSurfaceResized = false;
- result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
- }
if (displayPolicy.areSystemBarsForcedShownLw(win)) {
result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
}
@@ -2419,18 +2399,14 @@
// The last inset values represent the last client state
win.updateLastInsetValues();
- win.getCompatFrame(outFrame);
- win.getInsetsForRelayout(outContentInsets, outVisibleInsets,
- outStableInsets);
- outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
- outBackdropFrame.set(win.getBackdropFrame(win.getFrame()));
+ win.fillClientWindowFrames(outFrames);
outInsetsState.set(win.getInsetsState(), win.isClientLocal());
if (DEBUG) {
Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth
+ ", requestedHeight=" + requestedHeight
+ ", viewVisibility=" + viewVisibility
- + "\nRelayout returning frame=" + outFrame
+ + "\nRelayout returning frame=" + outFrames.frame
+ ", surface=" + outSurfaceControl);
}
@@ -2440,8 +2416,7 @@
result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
if (DEBUG_LAYOUT) {
- Slog.v(TAG_WM,
- "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
+ Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames);
}
win.mInRelayout = false;
@@ -5753,19 +5728,6 @@
}
@Override
- public void setPipVisibility(boolean visible) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Caller does not hold permission "
- + android.Manifest.permission.STATUS_BAR);
- }
-
- synchronized (mGlobalLock) {
- mPolicy.setPipVisibilityLw(visible);
- }
- }
-
- @Override
public void statusBarVisibilityChanged(int displayId, int visibility) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 84a9c75..cf73def 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -209,7 +209,6 @@
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
-import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IApplicationToken;
@@ -233,6 +232,7 @@
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.window.ClientWindowFrames;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.KeyInterceptionInfo;
@@ -388,15 +388,6 @@
private final Configuration mTempConfiguration = new Configuration();
/**
- * The last content insets returned to the client in relayout. We use
- * these in the bounds animation to ensure we only observe inset changes
- * at the same time that a client resizes it's surface so that we may use
- * the geometryAppliesWithResize synchronization mechanism to keep
- * the contents in place.
- */
- final Rect mLastRelayoutContentInsets = new Rect();
-
- /**
* Set to true if we are waiting for this window to receive its
* given internal insets before laying out other windows based on it.
*/
@@ -437,6 +428,8 @@
private final WindowFrames mWindowFrames = new WindowFrames();
+ private final ClientWindowFrames mClientWindowFrames = new ClientWindowFrames();
+
/** The frames used to compute a temporal layout appearance. */
private WindowFrames mSimulatedWindowFrames;
@@ -1299,7 +1292,10 @@
return mWindowFrames.mRelFrame;
}
- /** Retrieves the frame of the display that this window was last laid out in. */
+ /**
+ * Gets the frame that excludes the area of side insets according to the layout parameter from
+ * {@link WindowManager.LayoutParams#setFitInsetsSides}.
+ */
Rect getDisplayFrame() {
return mWindowFrames.mDisplayFrame;
}
@@ -2504,7 +2500,7 @@
// unregister server channel first otherwise it complains about broken channel
if (mInputChannel != null) {
- mWmService.mInputManager.unregisterInputChannel(mInputChannel);
+ mWmService.mInputManager.unregisterInputChannel(mInputChannel.getToken());
mInputChannel.dispose();
mInputChannel = null;
@@ -3585,6 +3581,39 @@
return wpc != null && wpc.registeredForDisplayConfigChanges();
}
+ void fillClientWindowFrames(ClientWindowFrames outFrames) {
+ outFrames.frame.set(mWindowFrames.mCompatFrame);
+ outFrames.displayFrame.set(mWindowFrames.mDisplayFrame);
+ if (mInvGlobalScale != 1.0f && inSizeCompatMode()) {
+ outFrames.displayFrame.scale(mInvGlobalScale);
+ }
+
+ final Rect backdropFrame = outFrames.backdropFrame;
+ // When the task is docked, we send fullscreen sized backdropFrame as soon as resizing
+ // start even if we haven't received the relayout window, so that the client requests
+ // the relayout sooner. When dragging stops, backdropFrame needs to stay fullscreen
+ // until the window to small size, otherwise the multithread renderer will shift last
+ // one or more frame to wrong offset. So here we send fullscreen backdrop if either
+ // isDragResizing() or isDragResizeChanged() is true.
+ final boolean resizing = isDragResizing() || isDragResizeChanged();
+ if (!resizing || getWindowConfiguration().useWindowFrameForBackdrop()) {
+ // Surface position is now inherited from parent, and BackdropFrameRenderer uses
+ // backdrop frame to position content. Thus we just keep the size of backdrop frame,
+ // and remove the offset to avoid double offset from display origin.
+ backdropFrame.set(outFrames.frame);
+ backdropFrame.offsetTo(0, 0);
+ } else {
+ final DisplayInfo displayInfo = getDisplayInfo();
+ backdropFrame.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+ }
+ outFrames.displayCutout.set(mWindowFrames.mDisplayCutout.getDisplayCutout());
+
+ // TODO(b/149813814): Remove legacy insets.
+ outFrames.contentInsets.set(mWindowFrames.mLastContentInsets);
+ outFrames.visibleInsets.set(mWindowFrames.mLastVisibleInsets);
+ outFrames.stableInsets.set(mWindowFrames.mLastStableInsets);
+ }
+
void reportResized() {
// If the activity is scheduled to relaunch, skip sending the resized to ViewRootImpl now
// since it will be destroyed anyway. This also prevents the client from receiving
@@ -3616,23 +3645,18 @@
mWinAnimator.mSurfaceResized = false;
mWindowFrames.resetInsetsChanged();
- final Rect frame = mWindowFrames.mCompatFrame;
- final Rect contentInsets = mWindowFrames.mLastContentInsets;
- final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
- final Rect stableInsets = mWindowFrames.mLastStableInsets;
final MergedConfiguration mergedConfiguration = mLastReportedConfiguration;
final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING || useBLASTSync() || !mRedrawForSyncReported;
final boolean forceRelayout = reportOrientation || isDragResizeChanged() || !mRedrawForSyncReported;
final int displayId = getDisplayId();
- final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout();
+ fillClientWindowFrames(mClientWindowFrames);
mRedrawForSyncReported = true;
try {
- mClient.resized(frame, contentInsets, visibleInsets, stableInsets, reportDraw,
- mergedConfiguration, getBackdropFrame(frame), forceRelayout,
+ mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this),
- displayId, new DisplayCutout.ParcelableWrapper(displayCutout));
+ displayId);
if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(displayId);
@@ -3738,27 +3762,6 @@
return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
}
- Rect getBackdropFrame(Rect frame) {
- // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
- // start even if we haven't received the relayout window, so that the client requests
- // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen
- // until the window to small size, otherwise the multithread renderer will shift last
- // one or more frame to wrong offset. So here we send fullscreen backdrop if either
- // isDragResizing() or isDragResizeChanged() is true.
- boolean resizing = isDragResizing() || isDragResizeChanged();
- if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) {
- // Surface position is now inherited from parent, and BackdropFrameRenderer uses
- // backdrop frame to position content. Thus we just keep the size of backdrop frame, and
- // remove the offset to avoid double offset from display origin.
- mTmpRect.set(frame);
- mTmpRect.offsetTo(0, 0);
- return mTmpRect;
- }
- final DisplayInfo displayInfo = getDisplayInfo();
- mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
- return mTmpRect;
- }
-
private int getRootTaskId() {
final Task stack = getRootTask();
if (stack == null) {
@@ -5670,18 +5673,6 @@
}
}
- /**
- * Copy the inset values over so they can be sent back to the client when a relayout occurs.
- */
- void getInsetsForRelayout(Rect outContentInsets, Rect outVisibleInsets,
- Rect outStableInsets) {
- outContentInsets.set(mWindowFrames.mContentInsets);
- outVisibleInsets.set(mWindowFrames.mVisibleInsets);
- outStableInsets.set(mWindowFrames.mStableInsets);
-
- mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets);
- }
-
void getContentInsets(Rect outContentInsets) {
outContentInsets.set(mWindowFrames.mContentInsets);
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1bd712c..5e81400 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -126,11 +126,7 @@
* we must tell them application to resize (and thus redraw itself).
*/
boolean mSurfaceResized;
- /**
- * Whether we should inform the client on next relayoutWindow that
- * the surface has been resized since last time.
- */
- boolean mReportSurfaceResized;
+
WindowSurfaceController mSurfaceController;
private WindowSurfaceController mPendingDestroySurface;
@@ -872,7 +868,6 @@
}
if (mSurfaceResized) {
- mReportSurfaceResized = true;
mWin.getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
}
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 7e9e11d..95d4ba7 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -29,6 +29,7 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <binder/IPCThreadState.h>
#include <jni.h>
#include <processgroup/processgroup.h>
@@ -90,11 +91,20 @@
}
}
+static void com_android_server_am_CachedAppOptimizer_freezeBinder(
+ JNIEnv *env, jobject clazz, jint pid, jboolean freeze) {
+
+ if (IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */) != 0) {
+ jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder");
+ }
+}
+
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"enableFreezerInternal", "(Z)V",
(void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal},
+ {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}
};
int register_android_server_am_CachedAppOptimizer(JNIEnv* env)
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 5dd6cd7..46136ca 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -209,7 +209,7 @@
status_t registerInputChannel(JNIEnv* env, const std::shared_ptr<InputChannel>& inputChannel);
status_t registerInputMonitor(JNIEnv* env, const std::shared_ptr<InputChannel>& inputChannel,
int32_t displayId, bool isGestureMonitor);
- status_t unregisterInputChannel(JNIEnv* env, const InputChannel& inputChannel);
+ status_t unregisterInputChannel(JNIEnv* env, const sp<IBinder>& connectionToken);
status_t pilferPointers(const sp<IBinder>& token);
void displayRemoved(JNIEnv* env, int32_t displayId);
@@ -447,9 +447,9 @@
}
status_t NativeInputManager::unregisterInputChannel(JNIEnv* /* env */,
- const InputChannel& inputChannel) {
+ const sp<IBinder>& connectionToken) {
ATRACE_CALL();
- return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
+ return mInputManager->getDispatcher()->unregisterInputChannel(connectionToken);
}
status_t NativeInputManager::pilferPointers(const sp<IBinder>& token) {
@@ -1364,7 +1364,7 @@
ALOGW("Input channel object '%s' was disposed without first being unregistered with "
"the input manager!", inputChannel->getName().c_str());
- im->unregisterInputChannel(env, *inputChannel);
+ im->unregisterInputChannel(env, inputChannel->getConnectionToken());
}
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
@@ -1417,20 +1417,12 @@
}
}
-static void nativeUnregisterInputChannel(JNIEnv* env, jclass /* clazz */,
- jlong ptr, jobject inputChannelObj) {
+static void nativeUnregisterInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
+ jobject tokenObj) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ sp<IBinder> token = ibinderForJavaObject(env, tokenObj);
- std::shared_ptr<InputChannel> inputChannel =
- android_view_InputChannel_getInputChannel(env, inputChannelObj);
- if (inputChannel == nullptr) {
- throwInputChannelNotInitialized(env);
- return;
- }
-
- android_view_InputChannel_setDisposeCallback(env, inputChannelObj, nullptr, nullptr);
-
- status_t status = im->unregisterInputChannel(env, *inputChannel);
+ status_t status = im->unregisterInputChannel(env, token);
if (status && status != BAD_VALUE) { // ignore already unregistered channel
std::string message;
message += StringPrintf("Failed to unregister input channel. status=%d", status);
@@ -1792,7 +1784,7 @@
(void*)nativeRegisterInputChannel},
{"nativeRegisterInputMonitor", "(JLandroid/view/InputChannel;IZ)V",
(void*)nativeRegisterInputMonitor},
- {"nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
+ {"nativeUnregisterInputChannel", "(JLandroid/os/IBinder;)V",
(void*)nativeUnregisterInputChannel},
{"nativePilferPointers", "(JLandroid/os/IBinder;)V", (void*)nativePilferPointers},
{"nativeSetInputFilterEnabled", "(JZ)V", (void*)nativeSetInputFilterEnabled},
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0d3d73f..e85bbd9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2159,6 +2159,11 @@
return getDeviceOwnerOfCallerLocked(caller);
}
+ @NonNull ActiveAdmin getParentOfAdminIfRequired(ActiveAdmin admin, boolean parent) {
+ Objects.requireNonNull(admin);
+ return parent ? admin.getParentActiveAdmin() : admin;
+ }
+
/**
* Finds an active admin for the caller then checks {@code permission} if admin check failed.
*
@@ -4527,6 +4532,8 @@
}
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
// timeoutMs with value 0 means that the admin doesn't participate
// timeoutMs is clamped to the interval in case the internal constants change in the future
final long minimumStrongAuthTimeout = getMinimumStrongAuthTimeoutMs();
@@ -4537,11 +4544,11 @@
timeoutMs = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
}
- final int userHandle = mInjector.userHandleGetCallingUserId();
+ final int userHandle = caller.getUserId();
boolean changed = false;
synchronized (getLockObject()) {
- ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ ActiveAdmin ap = getParentOfAdminIfRequired(getProfileOwnerOrDeviceOwnerLocked(caller),
+ parent);
if (ap.strongAuthUnlockTimeout != timeoutMs) {
ap.strongAuthUnlockTimeout = timeoutMs;
saveSettingsLocked(userHandle);
@@ -5646,8 +5653,9 @@
List<String> lockdownWhitelist)
throws SecurityException {
enforceProfileOrDeviceOwner(who);
+ final CallerIdentity caller = getCallerIdentity(who);
- final int userId = mInjector.userHandleGetCallingUserId();
+ final int userId = caller.getUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage);
@@ -5678,8 +5686,7 @@
.write();
});
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
if (!TextUtils.equals(vpnPackage, admin.mAlwaysOnVpnPackage)
|| lockdown != admin.mAlwaysOnVpnLockdown) {
admin.mAlwaysOnVpnPackage = vpnPackage;
@@ -9680,10 +9687,11 @@
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
- final ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
+ getProfileOwnerOrDeviceOwnerLocked(caller), parent);
if (parent) {
enforceProfileOwnerOfOrganizationOwnedDevice(activeAdmin);
}
@@ -9934,6 +9942,7 @@
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
/*
* When called on the parent DPM instance (parent == true), affects active admin
@@ -9941,9 +9950,14 @@
* * The ActiveAdmin must be of an org-owned profile owner.
* * The parent ActiveAdmin instance should be used for managing the restriction.
*/
- ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- parent ? DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER
- : DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ final ActiveAdmin ap;
+ if (parent) {
+ ap = getParentOfAdminIfRequired(getOrganizationOwnedProfileOwnerLocked(caller),
+ parent);
+ } else {
+ ap = getParentOfAdminIfRequired(getProfileOwnerOrDeviceOwnerLocked(caller), parent);
+ }
+
if (disabled) {
ap.accountTypesWithManagementDisabled.add(accountType);
} else {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 12c69ea..ddd1f75 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -16,6 +16,11 @@
package com.android.server.profcollect;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
@@ -34,6 +39,7 @@
import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
/**
* System-server-local proxy into the {@code IProfcollectd} native service.
@@ -41,28 +47,43 @@
public final class ProfcollectForwardingService extends SystemService {
public static final String LOG_TAG = "ProfcollectForwardingService";
+ private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
+
+ private static final long BG_PROCESS_PERIOD = DEBUG
+ ? TimeUnit.MINUTES.toMillis(1)
+ : TimeUnit.DAYS.toMillis(1);
+
private IProfCollectd mIProfcollect;
- private ProfcollectForwardingService mSelfService;
+ private static ProfcollectForwardingService sSelfService;
private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());
public ProfcollectForwardingService(Context context) {
super(context);
- if (mSelfService != null) {
+ if (sSelfService != null) {
throw new AssertionError("only one service instance allowed");
}
- mSelfService = this;
+ sSelfService = this;
}
@Override
public void onStart() {
- Log.i(LOG_TAG, "Profcollect forwarding service start");
- connectNativeService();
- if (mIProfcollect == null) {
- return;
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Profcollect forwarding service start");
}
- if (serviceHasSupportedTraceProvider()) {
- registerObservers();
+ connectNativeService();
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_BOOT_COMPLETED) {
+ if (mIProfcollect == null) {
+ return;
+ }
+ if (serviceHasSupportedTraceProvider()) {
+ registerObservers();
+ }
+ ProfcollectBGJobService.schedule(getContext());
}
}
@@ -130,6 +151,50 @@
}
}
+ /**
+ * Background trace process service.
+ */
+ public static class ProfcollectBGJobService extends JobService {
+ // Unique ID in system service
+ private static final int JOB_IDLE_PROCESS = 260817;
+ private static final ComponentName JOB_SERVICE_NAME = new ComponentName(
+ "android",
+ ProfcollectBGJobService.class.getName());
+
+ /**
+ * Attach the service to the system job scheduler.
+ */
+ public static void schedule(Context context) {
+ JobScheduler js = context.getSystemService(JobScheduler.class);
+
+ js.schedule(new JobInfo.Builder(JOB_IDLE_PROCESS, JOB_SERVICE_NAME)
+ .setRequiresDeviceIdle(true)
+ .setRequiresCharging(true)
+ .setPeriodic(BG_PROCESS_PERIOD)
+ .build());
+ }
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Starting background process job");
+ }
+
+ try {
+ sSelfService.mIProfcollect.ProcessProfile();
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, e.getMessage());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ // TODO: Handle this?
+ return false;
+ }
+ }
+
// Event observers
private void registerObservers() {
registerAppLaunchObserver();
@@ -155,7 +220,9 @@
int randomNum = ThreadLocalRandom.current().nextInt(100);
if (randomNum < traceFrequency) {
try {
- Log.i(LOG_TAG, "Tracing on app launch event: " + packageName);
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Tracing on app launch event: " + packageName);
+ }
mIProfcollect.TraceOnce("applaunch");
} catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage());
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 4f636ef..a941331 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -21,12 +21,15 @@
"truth-prebuilt",
],
static_libs: [
+ "cts-host-utils",
"frameworks-base-hostutils",
"PackageManagerServiceHostTestsIntentVerifyUtils",
],
test_suites: ["general-tests"],
java_resources: [
+ ":PackageManagerTestAppDeclaresStaticLibrary",
":PackageManagerTestAppStub",
+ ":PackageManagerTestAppUsesStaticLibrary",
":PackageManagerTestAppVersion1",
":PackageManagerTestAppVersion2",
":PackageManagerTestAppVersion3",
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
index 24c714c..9399030 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt
@@ -18,6 +18,7 @@
import com.android.internal.util.test.SystemPreparer
import com.android.tradefed.device.ITestDevice
+import com.google.common.truth.Truth
import org.junit.rules.TemporaryFolder
import java.io.File
import java.io.FileOutputStream
@@ -48,6 +49,44 @@
internal fun ITestDevice.uninstallPackages(vararg pkgNames: String) =
pkgNames.forEach { uninstallPackage(it) }
+/**
+ * Retry [block] a total of [maxAttempts] times, waiting [millisBetweenAttempts] milliseconds
+ * between each iteration, until a non-null result is returned, providing that result back to the
+ * caller.
+ *
+ * If an [AssertionError] is thrown by the [block] and a non-null result is never returned, that
+ * error will be re-thrown. This allows the use of [Truth.assertThat] to indicate success while
+ * providing a meaningful error message in case of failure.
+ */
+internal fun <T> retryUntilNonNull(
+ maxAttempts: Int = 10,
+ millisBetweenAttempts: Long = 1000,
+ block: () -> T?
+): T {
+ var attempt = 0
+ var failure: AssertionError? = null
+ while (attempt++ < maxAttempts) {
+ val result = try {
+ block()
+ } catch (e: AssertionError) {
+ failure = e
+ null
+ }
+
+ if (result != null) {
+ return result
+ } else {
+ Thread.sleep(millisBetweenAttempts)
+ }
+ }
+
+ throw failure ?: AssertionError("Never succeeded")
+}
+
+internal fun retryUntilSuccess(block: () -> Boolean) {
+ retryUntilNonNull { block().takeIf { it } }
+}
+
internal object HostUtils {
fun getDataDir(device: ITestDevice, pkgName: String) =
@@ -78,6 +117,25 @@
* dumpsys package and therefore device.getAppPackageInfo doesn't work immediately after reboot,
* so the following methods parse the package dump directly to see if the path matches.
*/
+
+ /**
+ * Reads the pm dump for a package name starting from the Packages: metadata section until
+ * the following section.
+ */
+ fun packageSection(
+ device: ITestDevice,
+ pkgName: String,
+ sectionName: String = "Packages"
+ ) = device.executeShellCommand("pm dump $pkgName")
+ .lineSequence()
+ .dropWhile { !it.startsWith(sectionName) } // Wait until the header
+ .drop(1) // Drop the header itself
+ .takeWhile {
+ // Until next top level header, a non-empty line that doesn't start with whitespace
+ it.isEmpty() || it.first().isWhitespace()
+ }
+ .map(String::trim)
+
fun getCodePaths(device: ITestDevice, pkgName: String) =
device.executeShellCommand("pm dump $pkgName")
.lineSequence()
@@ -87,14 +145,7 @@
.toList()
private fun userIdLineSequence(device: ITestDevice, pkgName: String) =
- device.executeShellCommand("pm dump $pkgName")
- .lineSequence()
- .dropWhile { !it.startsWith("Packages:") }
- .takeWhile {
- !it.startsWith("Hidden system packages:") &&
- !it.startsWith("Queries:")
- }
- .map(String::trim)
+ packageSection(device, pkgName)
.filter { it.startsWith("User ") }
fun getUserIdToPkgEnabledState(device: ITestDevice, pkgName: String) =
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt
new file mode 100644
index 0000000..9f9e6a3
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2020 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.server.pm.test
+
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters
+import android.cts.host.utils.DeviceJUnit4Parameterized
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.io.File
+import java.util.regex.Pattern
+
+/**
+ * Verifies PackageManagerService behavior when an app is moved to an adoptable storage device.
+ *
+ * Also has the effect of verifying system behavior when the PackageSetting for a package has no
+ * corresponding AndroidPackage which can be parsed from the APK on disk. This is done by removing
+ * the storage device and causing a reboot, at which point PMS will read PackageSettings from disk
+ * and fail to find the package path.
+ */
+@RunWith(DeviceJUnit4Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(
+ DeviceJUnit4ClassRunnerWithParameters.RunnerFactory::class)
+class SdCardEjectionTests : BaseHostJUnit4Test() {
+
+ companion object {
+ private const val VERSION_DECLARES = "PackageManagerTestAppDeclaresStaticLibrary.apk"
+ private const val VERSION_DECLARES_PKG_NAME =
+ "com.android.server.pm.test.test_app_declares_static_library"
+ private const val VERSION_USES = "PackageManagerTestAppUsesStaticLibrary.apk"
+ private const val VERSION_USES_PKG_NAME =
+ "com.android.server.pm.test.test_app_uses_static_library"
+
+ // TODO(chiuwinson): Use the HostUtils constants when merged
+ private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
+ private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
+
+ @Parameterized.Parameters(name = "reboot={0}")
+ @JvmStatic
+ fun parameters() = arrayOf(false, true)
+
+ data class Volume(
+ val diskId: String,
+ val fsUuid: String
+ )
+ }
+
+ @Rule
+ @JvmField
+ val tempFolder = TemporaryFolder()
+
+ @Parameterized.Parameter(0)
+ @JvmField
+ var reboot: Boolean = false
+
+ @Before
+ @After
+ fun removePackagesAndDeleteVirtualDisk() {
+ device.uninstallPackages(VERSION_ONE, VERSION_USES_PKG_NAME, VERSION_DECLARES_PKG_NAME)
+ removeVirtualDisk()
+ device.reboot()
+ }
+
+ @Test
+ fun launchActivity() {
+ val hostApkFile = HostUtils.copyResourceToHostFile(VERSION_ONE, tempFolder.newFile())
+ assertThat(device.installPackage(hostApkFile, true)).isNull()
+
+ val errorRegex = Pattern.compile("error", Pattern.CASE_INSENSITIVE)
+ fun assertStartResponse(launched: Boolean) {
+ val response = device.executeShellCommand("am start -n $TEST_PKG_NAME/.TestActivity")
+ if (launched) {
+ assertThat(response).doesNotContainMatch(errorRegex)
+ } else {
+ assertThat(response).containsMatch(errorRegex)
+ }
+ }
+
+ assertStartResponse(launched = true)
+
+ val volume = initializeVirtualDisk()
+
+ movePackage(TEST_PKG_NAME, volume)
+ assertStartResponse(launched = true)
+
+ unmount(volume, TEST_PKG_NAME)
+ assertStartResponse(launched = false)
+
+ remount(volume, hostApkFile, TEST_PKG_NAME)
+ assertStartResponse(launched = true)
+ }
+
+ @Test
+ fun uninstallStaticLibraryInUse() {
+ assertThat(device.installJavaResourceApk(tempFolder, VERSION_DECLARES)).isNull()
+
+ val usesApkFile = HostUtils.copyResourceToHostFile(VERSION_USES, tempFolder.newFile())
+ assertThat(device.installPackage(usesApkFile, true)).isNull()
+
+ fun assertUninstallFails() = assertThat(device.uninstallPackage(VERSION_DECLARES_PKG_NAME))
+ .isEqualTo("DELETE_FAILED_USED_SHARED_LIBRARY")
+
+ assertUninstallFails()
+
+ val volume = initializeVirtualDisk()
+
+ movePackage(VERSION_USES_PKG_NAME, volume)
+ assertUninstallFails()
+
+ unmount(volume, VERSION_USES_PKG_NAME)
+ assertUninstallFails()
+
+ remount(volume, usesApkFile, VERSION_USES_PKG_NAME)
+ assertUninstallFails()
+
+ // Check that install in the correct order (uses first) passes
+ assertThat(device.uninstallPackage(VERSION_USES_PKG_NAME)).isNull()
+ assertThat(device.uninstallPackage(VERSION_DECLARES_PKG_NAME)).isNull()
+ }
+
+ private fun initializeVirtualDisk(): Volume {
+ // Rather than making any assumption about what disks/volumes exist on the device,
+ // save the existing disks/volumes to compare and see when a new one pops up, assuming
+ // it was created as the result of the calls in this test.
+ val existingDisks = device.executeShellCommand("sm list-disks adoptable").lines()
+ val existingVolumes = device.executeShellCommand("sm list-volumes private").lines()
+ device.executeShellCommand("sm set-virtual-disk true")
+
+ val diskId = retryUntilNonNull {
+ device.executeShellCommand("sm list-disks adoptable")
+ .lines()
+ .filterNot(existingDisks::contains)
+ .filterNot(String::isEmpty)
+ .firstOrNull()
+ }
+
+ device.executeShellCommand("sm partition $diskId private")
+
+ return retrieveNewVolume(existingVolumes)
+ }
+
+ private fun retrieveNewVolume(existingVolumes: List<String>): Volume {
+ val newVolume = retryUntilNonNull {
+ device.executeShellCommand("sm list-volumes private")
+ .lines()
+ .toMutableList()
+ .apply { removeAll(existingVolumes) }
+ .firstOrNull()
+ ?.takeIf { it.isNotEmpty() }
+ }
+
+ val sections = newVolume.split(" ")
+ return Volume(diskId = sections.first(), fsUuid = sections.last()).also {
+ assertThat(it.diskId).isNotEmpty()
+ assertThat(it.fsUuid).isNotEmpty()
+ }
+ }
+
+ private fun removeVirtualDisk() {
+ device.executeShellCommand("sm set-virtual-disk false")
+ retryUntilSuccess {
+ !device.executeShellCommand("sm list-volumes").contains("ejecting")
+ }
+ }
+
+ private fun movePackage(pkgName: String, volume: Volume) {
+ // TODO(b/167241596): oat dir must exist for a move install
+ val codePath = HostUtils.getCodePaths(device, pkgName).first()
+ device.executeShellCommand("mkdir $codePath/oat")
+ assertThat(device.executeShellCommand(
+ "pm move-package $pkgName ${volume.fsUuid}").trim())
+ .isEqualTo("Success")
+ }
+
+ private fun unmount(volume: Volume, pkgName: String) {
+ assertThat(device.executeShellCommand("sm unmount ${volume.diskId}")).isEmpty()
+ if (reboot) {
+ // The system automatically mounts the virtual disk on startup, which would mean the
+ // app files are available to the system. To prevent this, disable the disk entirely.
+ // TODO: There must be a better way to prevent it from auto-mounting.
+ removeVirtualDisk()
+ device.reboot()
+ } else {
+ // Because PackageManager unmount scan is asynchronous, need to retry until the package
+ // has been unloaded. This only has to be done in the non-reboot case. Reboot will
+ // clear the data structure by its nature.
+ retryUntilSuccess {
+ // The compiler section will print the state of the physical APK
+ HostUtils.packageSection(device, pkgName, sectionName = "Compiler stats")
+ .any { it.contains("Unable to find package: $pkgName") }
+ }
+ }
+ }
+
+ private fun remount(volume: Volume, hostApkFile: File, pkgName: String) {
+ if (reboot) {
+ // Because the disk was destroyed when unmounting, it now has to be rebuilt manually.
+ // This enables a new virtual disk, unmounts it, mutates its UUID to match the previous
+ // partition's, remounts it, and pushes the base.apk back onto the device. This
+ // simulates the same disk being re-inserted. This is very hacky.
+ val newVolume = initializeVirtualDisk()
+ val mountPoint = device.executeShellCommand("mount")
+ .lineSequence()
+ .first { it.contains(newVolume.fsUuid) }
+ .takeWhile { !it.isWhitespace() }
+
+ device.executeShellCommand("sm unmount ${newVolume.diskId}")
+
+ // Save without renamed UUID to compare and see when the renamed pops up
+ val existingVolumes = device.executeShellCommand("sm list-volumes private").lines()
+
+ device.executeShellCommand("make_f2fs -U ${volume.fsUuid} $mountPoint")
+ device.executeShellCommand("sm mount ${newVolume.diskId}")
+
+ val reparsedVolume = retrieveNewVolume(existingVolumes)
+ assertThat(reparsedVolume.fsUuid).isEqualTo(volume.fsUuid)
+
+ val codePath = HostUtils.getCodePaths(device, pkgName).first()
+ device.pushFile(hostApkFile, "$codePath/base.apk")
+
+ // Unmount so following remount will re-kick package scan
+ device.executeShellCommand("sm unmount ${newVolume.diskId}")
+ }
+
+ device.executeShellCommand("sm mount ${volume.diskId}")
+
+ // Because PackageManager remount scan is asynchronous, need to retry until the package
+ // has been loaded and added to the internal structures. Otherwise resolution will fail.
+ retryUntilSuccess {
+ // The compiler section will print the state of the physical APK
+ HostUtils.packageSection(device, pkgName, sectionName = "Compiler stats")
+ .none { it.contains("Unable to find package: $pkgName") }
+ }
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
similarity index 100%
rename from services/tests/PackageManagerServiceTests/host/test-apps/Android.bp
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestOriginalOverride.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestOriginalOverride.xml
similarity index 100%
rename from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestOriginalOverride.xml
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestOriginalOverride.xml
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion1.xml
similarity index 84%
rename from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion1.xml
index efc7372..05b6248 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion1.xml
@@ -25,4 +25,9 @@
android:protectionLevel="normal"
/>
+ <application>
+ <activity android:name="com.android.server.pm.test.test_app.TestActivity"
+ android:label="PackageManagerTestApp" />
+ </application>
+
</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion2.xml
similarity index 97%
rename from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion2.xml
index 620054c..d6eb3e0 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion2.xml
@@ -25,4 +25,6 @@
android:protectionLevel="normal"
/>
+ <application/>
+
</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion3.xml
similarity index 97%
rename from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion3.xml
index 1997771..90317cb 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion3.xml
@@ -25,4 +25,6 @@
android:protectionLevel="normal"
/>
+ <application/>
+
</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion4.xml
similarity index 97%
rename from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml
rename to services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion4.xml
index d6ade03..795c3c1 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion4.xml
@@ -25,4 +25,6 @@
android:protectionLevel="normal"
/>
+ <application/>
+
</manifest>
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt
similarity index 61%
copy from packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
copy to services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt
index e65f19d..0c9b8d4 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,17 +14,8 @@
* limitations under the License.
*/
-package com.android.keyguard.dagger;
+package com.android.server.pm.test.test_app
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import android.app.Activity
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface ContainerView {
-}
+class TestActivity : Activity()
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
new file mode 100644
index 0000000..58f17f2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2020 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.
+
+android_test_helper_app {
+ name: "PackageManagerTestAppDeclaresStaticLibrary",
+ manifest: "AndroidManifestDeclaresStaticLibrary.xml",
+ certificate: ":FrameworksCoreTests_keyset_A_cert",
+}
+
+android_test_helper_app {
+ name: "PackageManagerTestAppUsesStaticLibrary",
+ manifest: "AndroidManifestUsesStaticLibrary.xml",
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml
similarity index 64%
copy from services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
copy to services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml
index 1997771..8a6c01a 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,15 +13,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.server.pm.test.test_app"
- android:versionCode="3"
- >
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.pm.test.test_app_declares_static_library">
- <permission
- android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
- android:protectionLevel="normal"
- />
+ <application>
+ <static-library android:name="com.android.server.pm.test.static_library"
+ android:version="1" />
+ </application>
</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml
new file mode 100644
index 0000000..82d9ac4
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2020 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.pm.test.test_app_uses_static_library">
+
+ <application>
+ <activity android:name="com.android.server.pm.test.static_library.TestActivity"
+ android:label="TestActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <uses-static-library android:name="com.android.server.pm.test.static_library"
+ android:certDigest="1F:BE:5F:FB:B0:AD:DC:0C:CD:BF:22:B9:8A:2F:5A:58:A5:C8:29:80:E1:30:2F:65:0E:6B:CA:ED:03:82:BF:CF"
+ android:version="1" />
+ </application>
+
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt
new file mode 100644
index 0000000..fa85258
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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.server.pm.test.static_library
+
+import android.app.Activity
+import android.graphics.Color
+import android.os.Bundle
+import android.view.ViewGroup
+import android.widget.FrameLayout
+
+class TestActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(FrameLayout(this).apply {
+ setBackgroundColor(Color.BLUE)
+ }, ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ ))
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 82726c7..5d8f662 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -173,6 +173,8 @@
mock(OomAdjProfiler.class));
setFieldValue(ActivityManagerService.class, sService, "mUserController",
mock(UserController.class));
+ setFieldValue(ActivityManagerService.class, sService, "mAppProfiler",
+ mock(AppProfiler.class));
doReturn(new ActivityManagerService.ProcessChangeItem()).when(sService)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index c8baca6..8062bfe 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -170,6 +170,30 @@
verify(mMockSystemSupport).onClientChangeLocked(false);
}
+ @Test
+ public void uiAutomationWithDontUseAccessibilityFlagAfterUnregistering_notifiesSystem()
+ throws Exception {
+ register(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY);
+ unregister();
+ verify(mMockSystemSupport).onClientChangeLocked(false);
+ }
+
+ @Test
+ public void uiAutomationWithDontUseAccessibilityFlag_disableAccessibilityFunctions()
+ throws Exception {
+ register(0);
+ assertTrue(mUiAutomationManager.isUiAutomationRunningLocked());
+ unregister();
+ assertFalse(mUiAutomationManager.isUiAutomationRunningLocked());
+ register(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY);
+ assertTrue(mUiAutomationManager.isUiAutomationRunningLocked());
+ assertFalse(mUiAutomationManager.useAccessibility());
+ assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
+ assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked());
+ assertEquals(0, mUiAutomationManager.getRelevantEventTypes());
+ assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked());
+ }
+
private void register(int flags) {
mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner,
mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID,
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 1d04c83..e02a46af 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -24,7 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.ActivityManager;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -984,8 +984,8 @@
}
@Override
- public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
- ActivityManager.StackInfo focusedStack = new ActivityManager.StackInfo();
+ public RootTaskInfo getFocusedStack() throws RemoteException {
+ RootTaskInfo focusedStack = new RootTaskInfo();
focusedStack.userId = 0;
focusedStack.topActivity = new ComponentName("a.package", "a.class");
return focusedStack;
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
index 0839273..154d42c 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
@@ -21,172 +21,387 @@
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.os.Process
-import org.junit.Rule
+import com.android.server.om.OverlayActorEnforcer.ActorState
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.BeforeClass
import org.junit.Test
-import org.junit.rules.ExpectedException
-import java.lang.UnsupportedOperationException
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.Mockito.spy
+import java.io.IOException
+@RunWith(Parameterized::class)
class OverlayActorEnforcerTests {
+
companion object {
- private const val NAMESPACE = "testnamespace"
- private const val ACTOR_NAME = "testactor"
- private const val ACTOR_PKG_NAME = "com.test.actor.one"
+ private const val TARGET_PKG = "com.test.target"
+ private const val OVERLAY_PKG = "com.test.overlay"
+
+ private const val VALID_NAMESPACE = "testNamespaceValid"
+ private const val INVALID_NAMESPACE = "testNamespaceInvalid"
+ private const val VALID_ACTOR_NAME = "testActorOne"
+ private const val INVALID_ACTOR_NAME = "testActorTwo"
+ private const val VALID_ACTOR_PKG = "com.test.actor.valid"
+ private const val INVALID_ACTOR_PKG = "com.test.actor.invalid"
private const val OVERLAYABLE_NAME = "TestOverlayable"
- private const val UID = 3536
+ private const val NULL_UID = 3536
+ private const val EMPTY_UID = NULL_UID + 1
+ private const val INVALID_ACTOR_UID = NULL_UID + 2
+ private const val VALID_ACTOR_UID = NULL_UID + 3
+ private const val TARGET_UID = NULL_UID + 4
private const val USER_ID = 55
- }
- @get:Rule
- val expectedException = ExpectedException.none()!!
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun parameters() = CASES.mapIndexed { caseIndex, testCase ->
+ fun param(pair: Pair<String, TestState.() -> Unit>, type: Params.Type): Params {
+ val expectedState = testCase.state.takeUnless { type == Params.Type.ALLOWED }
+ ?: ActorState.ALLOWED
+ val (caseName, case) = pair
+ val testName = makeTestName(testCase, caseName, type)
+ return Params(caseIndex, expectedState, testName, type, case)
+ }
- @Test
- fun isRoot() {
- verify(callingUid = Process.ROOT_UID)
- }
+ testCase.failures.map { param(it, Params.Type.FAILURE) } +
+ testCase.allowed.map { param(it, Params.Type.ALLOWED) }
+ }.flatten()
- @Test(expected = SecurityException::class)
- fun isShell() {
- verify(callingUid = Process.SHELL_UID)
- }
-
- @Test
- fun isSystem() {
- verify(callingUid = Process.SYSTEM_UID)
- }
-
- @Test(expected = SecurityException::class)
- fun noOverlayable_noTarget() {
- verify(targetOverlayableName = null)
- }
-
- @Test
- fun noOverlayable_noTarget_withPermission() {
- verify(targetOverlayableName = null, hasPermission = true)
- }
-
- @Test(expected = SecurityException::class)
- fun noOverlayable_withTarget() {
- verify(targetOverlayableName = OVERLAYABLE_NAME)
- }
-
- @Test(expected = SecurityException::class)
- fun withOverlayable_noTarget() {
- verify(
- targetOverlayableName = null,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
- )
- }
-
- @Test(expected = SecurityException::class)
- fun withOverlayable_noActor() {
- verify(
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
- )
- }
-
- @Test
- fun withOverlayable_noActor_withPermission() {
- verify(
- hasPermission = true,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
- )
- }
-
- @Test(expected = SecurityException::class)
- fun withOverlayable_withActor_notActor() {
- verify(
- isActor = false,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
- "overlay://$NAMESPACE/$ACTOR_NAME")
- )
- }
-
- @Test(expected = SecurityException::class)
- fun withOverlayable_withActor_isActor_notPreInstalled() {
- verify(
- isActor = true,
- isPreInstalled = false,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
- "overlay://$NAMESPACE/$ACTOR_NAME")
- )
- }
-
- @Test
- fun withOverlayable_withActor_isActor_isPreInstalled() {
- verify(
- isActor = true,
- isPreInstalled = true,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
- "overlay://$NAMESPACE/$ACTOR_NAME")
- )
- }
-
- @Test(expected = SecurityException::class)
- fun withOverlayable_invalidActor() {
- verify(
- isActor = true,
- isPreInstalled = true,
- overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor")
- )
- }
-
- private fun verify(
- isActor: Boolean = false,
- isPreInstalled: Boolean = false,
- hasPermission: Boolean = false,
- overlayableInfo: OverlayableInfo? = null,
- callingUid: Int = UID,
- targetOverlayableName: String? = OVERLAYABLE_NAME
- ) {
- val callback = MockCallback(
- isActor = isActor,
- isPreInstalled = isPreInstalled,
- hasPermission = hasPermission,
- overlayableInfo = overlayableInfo
- )
-
- val overlayInfo = overlayInfo(targetOverlayableName)
- OverlayActorEnforcer(callback)
- .enforceActor(overlayInfo, "test", callingUid, USER_ID)
- }
-
- private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay",
- "com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0,
- 0, false)
-
- private class MockCallback(
- private val isActor: Boolean = false,
- private val isPreInstalled: Boolean = false,
- private val hasPermission: Boolean = false,
- private val overlayableInfo: OverlayableInfo? = null,
- private vararg val packageNames: String = arrayOf("com.test.actor.one")
- ) : PackageManagerHelper {
-
- override fun getNamedActors() = if (isActor) {
- mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
- } else {
- emptyMap()
+ @BeforeClass
+ @JvmStatic
+ fun checkAllCasesHandled() {
+ // Assert that all states have been tested at least once.
+ assertThat(CASES.map { it.state }.distinct()).containsAllIn(ActorState.values())
}
+ @BeforeClass
+ @JvmStatic
+ fun checkAllCasesUniquelyNamed() {
+ val duplicateCaseNames = CASES.mapIndexed { caseIndex, testCase ->
+ testCase.failures.map {
+ makeTestName(testCase, it.first, Params.Type.FAILURE)
+ } + testCase.allowed.map {
+ makeTestName(testCase, it.first, Params.Type.ALLOWED)
+ }
+ }
+ .flatten()
+ .groupingBy { it }
+ .eachCount()
+ .filterValues { it > 1 }
+ .keys
+
+ assertThat(duplicateCaseNames).isEmpty()
+ }
+
+ /*
+ The pattern in this block is a result of the incredible number of branches in
+ enforcement logic. It serves to verify failures with the assumption that all errors
+ are checked in order. The idea is to emulate the if-else branches from code, but using
+ actual test data instead of if statements.
+
+ Each state is verified by providing a failure or exclusive set of failures which cause
+ a failure state to be returned. Each state also provides a success case which will
+ "skip" the state. This allows subsequent failure cases to cascade from the first case
+ by calling all the skip branches for preceding states and then choosing only 1 of
+ the failures to test.
+
+ Given the failure states A, B, and C: testA calls A.failure + assert, testB calls
+ A.skip + B.failure + assert, testC calls A.skip + B.skip + C.failure + assert, etc.
+
+ Calling `allowed` is a special case for when there is a combination of parameters that
+ skips the remaining checks and immediately allows the actor through. For these cases,
+ the first failure branch will be run, assert that it's not allowed, and the
+ allowed branch will run, asserting that it now results in ALLOWED, skipping all
+ remaining functions.
+
+ This is an ordered list of TestCase objects, with the possibility to repeat failure
+ states if any can occur multiple times in the logic tree.
+
+ Each failure must be handled at least once.
+ */
+ private val CASES = listOf(
+ ActorState.TARGET_NOT_FOUND withCases {
+ failure("nullPkgInfo") { targetPkgInfo = null }
+ allowed("debuggable") {
+ targetPkgInfo = pkgInfo(TARGET_PKG).apply {
+ applicationInfo.flags = ApplicationInfo.FLAG_DEBUGGABLE
+ }
+ }
+ skip { targetPkgInfo = pkgInfo(TARGET_PKG) }
+ },
+ ActorState.NO_PACKAGES_FOR_UID withCases {
+ failure("empty") { callingUid = EMPTY_UID }
+ failure("null") { callingUid = NULL_UID }
+ failure("shell") { callingUid = Process.SHELL_UID }
+ allowed("targetUid") { callingUid = TARGET_UID }
+ allowed("rootUid") { callingUid = Process.ROOT_UID }
+ allowed("systemUid") { callingUid = Process.SYSTEM_UID }
+ skip { callingUid = INVALID_ACTOR_UID }
+ },
+ ActorState.MISSING_TARGET_OVERLAYABLE_NAME withCases {
+ failure("nullTargetOverlayableName") {
+ overlayInfoParams.targetOverlayableName = null
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME")
+ }
+ skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME }
+ },
+ ActorState.MISSING_LEGACY_PERMISSION withCases {
+ failure("noPermission") {
+ overlayInfoParams.targetOverlayableName = null
+ targetOverlayableInfo = null
+ hasPermission = false
+ }
+ allowed("hasPermission") { hasPermission = true }
+ skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME }
+ },
+ ActorState.ERROR_READING_OVERLAYABLE withCases {
+ failure("doesTargetDefineOverlayableIOException") {
+ overlayInfoParams.targetOverlayableName = null
+ whenever(doesTargetDefineOverlayable(TARGET_PKG, USER_ID))
+ .thenThrow(IOException::class.java)
+ }
+ skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME }
+ },
+ ActorState.UNABLE_TO_GET_TARGET_OVERLAYABLE withCases {
+ failure("getOverlayableForTargetIOException") {
+ whenever(getOverlayableForTarget(TARGET_PKG, OVERLAYABLE_NAME,
+ USER_ID)).thenThrow(IOException::class.java)
+ }
+ },
+ ActorState.MISSING_OVERLAYABLE withCases {
+ failure("nullTargetOverlayableInfo") { targetOverlayableInfo = null }
+ skip {
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME")
+ }
+ },
+ ActorState.MISSING_LEGACY_PERMISSION withCases {
+ failure("noPermissionNullActor") {
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
+ hasPermission = false
+ }
+ failure("noPermissionEmptyActor") {
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "")
+ hasPermission = false
+ }
+ allowed("hasPermissionNullActor") {
+ hasPermission = true
+ }
+ skip {
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
+ "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME")
+ }
+ },
+ ActorState.INVALID_OVERLAYABLE_ACTOR_NAME withCases {
+ fun TestState.mockActor(actorUri: String) {
+ targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, actorUri)
+ }
+ failure("wrongScheme") {
+ mockActor("notoverlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME")
+ }
+ failure("extraPath") {
+ mockActor("overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME/extraPath")
+ }
+ failure("missingPath") { mockActor("overlay://$VALID_NAMESPACE") }
+ failure("missingAuthority") { mockActor("overlay://") }
+ skip { mockActor("overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") }
+ },
+ ActorState.NO_NAMED_ACTORS withCases {
+ failure("empty") { namedActorsMap = emptyMap() }
+ skip {
+ namedActorsMap = mapOf(INVALID_NAMESPACE to
+ mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG))
+ }
+ },
+ ActorState.MISSING_NAMESPACE withCases {
+ failure("invalidNamespace") {
+ namedActorsMap = mapOf(INVALID_NAMESPACE to
+ mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG))
+ }
+ skip {
+ namedActorsMap = mapOf(VALID_NAMESPACE to
+ mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG))
+ }
+ },
+ ActorState.MISSING_ACTOR_NAME withCases {
+ failure("invalidActorName") {
+ namedActorsMap = mapOf(VALID_NAMESPACE to
+ mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG))
+ }
+ skip {
+ namedActorsMap = mapOf(VALID_NAMESPACE to
+ mapOf(VALID_ACTOR_NAME to VALID_ACTOR_PKG))
+ }
+ },
+ ActorState.MISSING_APP_INFO withCases {
+ failure("nullActorPkgInfo") { actorPkgInfo = null }
+ failure("nullActorAppInfo") {
+ actorPkgInfo = PackageInfo().apply { applicationInfo = null }
+ }
+ skip { actorPkgInfo = pkgInfo(VALID_ACTOR_PKG) }
+ },
+ ActorState.ACTOR_NOT_PREINSTALLED withCases {
+ failure("notSystem") {
+ actorPkgInfo = pkgInfo(VALID_ACTOR_PKG).apply {
+ applicationInfo.flags = 0
+ }
+ }
+ skip {
+ actorPkgInfo = pkgInfo(VALID_ACTOR_PKG).apply {
+ applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM
+ }
+ }
+ },
+ ActorState.INVALID_ACTOR withCases {
+ failure("invalidUid") { callingUid = INVALID_ACTOR_UID }
+ skip { callingUid = VALID_ACTOR_UID }
+ },
+ ActorState.ALLOWED withCases {
+ // No point making an exception for this case in all of the test code, so
+ // just pretend this is a failure that results in a success result code.
+ failure("allowed") { /* Do nothing */ }
+ }
+ )
+
+ data class OverlayInfoParams(
+ var targetPackageName: String = TARGET_PKG,
+ var targetOverlayableName: String? = null
+ ) {
+ fun toOverlayInfo() = OverlayInfo(
+ OVERLAY_PKG,
+ targetPackageName,
+ targetOverlayableName,
+ null,
+ "/path",
+ OverlayInfo.STATE_UNKNOWN, 0,
+ 0, false)
+ }
+
+ private infix fun ActorState.withCases(block: TestCase.() -> Unit) =
+ TestCase(this).apply(block)
+
+ private fun pkgInfo(pkgName: String): PackageInfo = mockThrowOnUnmocked {
+ this.packageName = pkgName
+ this.applicationInfo = ApplicationInfo().apply {
+ this.packageName = pkgName
+ }
+ }
+
+ private fun makeTestName(testCase: TestCase, caseName: String, type: Params.Type): String {
+ val resultSuffix = if (type == Params.Type.ALLOWED) "allowed" else "failed"
+ return "${testCase.state}_${resultSuffix}_$caseName"
+ }
+ }
+
+ @Parameterized.Parameter(0)
+ lateinit var params: Params
+
+ @Test
+ fun verify() {
+ // Apply all the skip states before the failure to be verified
+ val testState = CASES.take(params.index)
+ .fold(TestState.create()) { testState, case ->
+ testState.apply(case.skip)
+ }
+
+ // If testing an allowed branch, first apply a failure to ensure it fails
+ if (params.type == Params.Type.ALLOWED) {
+ CASES[params.index].failures.firstOrNull()?.second?.run(testState::apply)
+ assertThat(testState.toResult()).isNotEqualTo(ActorState.ALLOWED)
+ }
+
+ // Apply the test case in the params to the collected state
+ testState.apply(params.function)
+
+ // Assert the result matches the expected state
+ assertThat(testState.toResult()).isEqualTo(params.expectedState)
+ }
+
+ private fun TestState.toResult() = OverlayActorEnforcer(this)
+ .isAllowedActor("test", overlayInfoParams.toOverlayInfo(), callingUid, USER_ID)
+
+ data class Params(
+ var index: Int,
+ var expectedState: ActorState,
+ val testName: String,
+ val type: Type,
+ val function: TestState.() -> Unit
+ ) {
+ override fun toString() = testName
+
+ enum class Type {
+ FAILURE,
+ ALLOWED
+ }
+ }
+
+ data class TestCase(
+ val state: ActorState,
+ val failures: MutableList<Pair<String, TestState.() -> Unit>> = mutableListOf(),
+ var allowed: MutableList<Pair<String, TestState.() -> Unit>> = mutableListOf(),
+ var skip: (TestState.() -> Unit) = {}
+ ) {
+ fun failure(caseName: String, block: TestState.() -> Unit) {
+ failures.add(caseName to block)
+ }
+
+ fun allowed(caseName: String, block: TestState.() -> Unit) {
+ allowed.add(caseName to block)
+ }
+
+ fun skip(block: TestState.() -> Unit) {
+ this.skip = block
+ }
+ }
+
+ open class TestState private constructor(
+ var callingUid: Int = NULL_UID,
+ val overlayInfoParams: OverlayInfoParams = OverlayInfoParams(),
+ var namedActorsMap: Map<String, Map<String, String>> = emptyMap(),
+ var hasPermission: Boolean = false,
+ var targetOverlayableInfo: OverlayableInfo? = null,
+ var targetPkgInfo: PackageInfo? = null,
+ var actorPkgInfo: PackageInfo? = null,
+ vararg val packageNames: String = arrayOf("com.test.actor.one")
+ ) : PackageManagerHelper {
+
+ companion object {
+ // Enforce that new instances are spied
+ fun create() = spy(TestState())!!
+ }
+
+ override fun getNamedActors() = namedActorsMap
+
+ @Throws(IOException::class)
override fun getOverlayableForTarget(
packageName: String,
targetOverlayableName: String,
userId: Int
- ) = overlayableInfo
+ ) = targetOverlayableInfo?.takeIf {
+ // Protect against this method being called with the wrong package name
+ targetPkgInfo == null || targetPkgInfo?.packageName == packageName
+ }
override fun getPackagesForUid(uid: Int) = when (uid) {
- UID -> packageNames
+ EMPTY_UID -> emptyArray()
+ INVALID_ACTOR_UID -> arrayOf(INVALID_ACTOR_PKG)
+ VALID_ACTOR_UID -> arrayOf(VALID_ACTOR_PKG)
+ TARGET_UID -> arrayOf(TARGET_PKG)
+ NULL_UID -> null
else -> null
}
- override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply {
- applicationInfo = ApplicationInfo().apply {
- flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0
- }
- }
+ override fun getPackageInfo(packageName: String, userId: Int) =
+ listOfNotNull(targetPkgInfo, actorPkgInfo).find { it.packageName == packageName }
+ @Throws(IOException::class) // Mockito requires this checked exception to be declared
override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean {
- return overlayableInfo != null
+ return targetOverlayableInfo?.takeIf {
+ // Protect against this method being called with the wrong package name
+ targetPkgInfo == null || targetPkgInfo?.packageName == targetPackageName
+ } != null
}
override fun enforcePermission(permission: String?, message: String?) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 0bf06bb..dac0542 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -45,6 +45,7 @@
import android.content.pm.UserInfo;
import android.os.BaseBundle;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.util.ArrayMap;
@@ -59,8 +60,12 @@
import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.PermissionSettings;
+import com.google.common.truth.Truth;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -380,6 +385,74 @@
}
@Test
+ public void testWriteReadUsesStaticLibraries() {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final Object lock = new Object();
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
+ final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+ ps1.appId = Process.FIRST_APPLICATION_UID;
+ ps1.pkg = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+ .setUid(ps1.appId)
+ .setSystem(true)
+ .hideAsFinal();
+ final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
+ ps2.appId = Process.FIRST_APPLICATION_UID + 1;
+ ps2.pkg = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
+ .setUid(ps2.appId)
+ .hideAsFinal();
+
+ ps1.usesStaticLibraries = new String[] { "com.example.shared.one" };
+ ps1.usesStaticLibrariesVersions = new long[] { 12 };
+ ps1.setFlags(ps1.pkgFlags | ApplicationInfo.FLAG_SYSTEM);
+ settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
+ assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true));
+
+ ps2.usesStaticLibraries = new String[] { "com.example.shared.two" };
+ ps2.usesStaticLibrariesVersions = new long[] { 34 };
+ settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
+
+ settingsUnderTest.writeLPr();
+
+ settingsUnderTest.mPackages.clear();
+ settingsUnderTest.mDisabledSysPackages.clear();
+
+ assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true));
+
+ PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
+ PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
+
+ Truth.assertThat(readPs1).isNotNull();
+ Truth.assertThat(readPs1.usesStaticLibraries).isNotNull();
+ Truth.assertThat(readPs1.usesStaticLibrariesVersions).isNotNull();
+ Truth.assertThat(readPs2).isNotNull();
+ Truth.assertThat(readPs2.usesStaticLibraries).isNotNull();
+ Truth.assertThat(readPs2.usesStaticLibrariesVersions).isNotNull();
+
+ List<Long> ps1VersionsAsList = new ArrayList<>();
+ for (long version : ps1.usesStaticLibrariesVersions) {
+ ps1VersionsAsList.add(version);
+ }
+
+ List<Long> ps2VersionsAsList = new ArrayList<>();
+ for (long version : ps2.usesStaticLibrariesVersions) {
+ ps2VersionsAsList.add(version);
+ }
+
+ Truth.assertThat(readPs1.usesStaticLibraries).asList()
+ .containsExactlyElementsIn(ps1.usesStaticLibraries).inOrder();
+
+ Truth.assertThat(readPs1.usesStaticLibrariesVersions).asList()
+ .containsExactlyElementsIn(ps1VersionsAsList).inOrder();
+
+ Truth.assertThat(readPs2.usesStaticLibraries).asList()
+ .containsExactlyElementsIn(ps2.usesStaticLibraries).inOrder();
+
+ Truth.assertThat(readPs2.usesStaticLibrariesVersions).asList()
+ .containsExactlyElementsIn(ps2VersionsAsList).inOrder();
+ }
+
+ @Test
public void testPackageRestrictionsDistractionFlagsDefault() {
final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
assertThat(defaultSetting.getDistractionFlags(0), is(PackageManager.RESTRICTION_NONE));
@@ -617,7 +690,7 @@
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
- assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH));
+ assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
@@ -656,7 +729,7 @@
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(0));
- assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH));
+ assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
@@ -700,7 +773,7 @@
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(10064));
- assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH));
+ assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
@@ -741,7 +814,7 @@
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(10064));
- assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH));
+ assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
@@ -792,10 +865,10 @@
private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) {
assertThat(origPkgSetting, is(not(testPkgSetting)));
assertThat(origPkgSetting.appId, is(testPkgSetting.appId));
- assertSame(origPkgSetting.getCodePath(), testPkgSetting.getCodePath());
- assertThat(origPkgSetting.getCodePath(), is(testPkgSetting.getCodePath()));
- assertSame(origPkgSetting.getCodePathString(), testPkgSetting.getCodePathString());
- assertThat(origPkgSetting.getCodePathString(), is(testPkgSetting.getCodePathString()));
+ assertSame(origPkgSetting.getPath(), testPkgSetting.getPath());
+ assertThat(origPkgSetting.getPath(), is(testPkgSetting.getPath()));
+ assertSame(origPkgSetting.getPathString(), testPkgSetting.getPathString());
+ assertThat(origPkgSetting.getPathString(), is(testPkgSetting.getPathString()));
assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString);
assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString));
assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime));
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 2651cfa..1d384e9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -312,7 +312,7 @@
private static PackageSetting mockPkgSetting(AndroidPackage pkg) {
return new PackageSetting(pkg.getPackageName(), pkg.getRealPackage(),
- new File(pkg.getCodePath()), null, pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(),
+ new File(pkg.getPath()), null, pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(),
null, pkg.getVersionCode(),
PackageInfoUtils.appInfoFlags(pkg, null),
PackageInfoUtils.appInfoPrivateFlags(pkg, null),
@@ -335,8 +335,8 @@
assertEquals(a.getPackageName(), b.getPackageName());
assertArrayEquals(a.getSplitNames(), b.getSplitNames());
assertEquals(a.getVolumeUuid(), b.getVolumeUuid());
- assertEquals(a.getCodePath(), b.getCodePath());
- assertEquals(a.getBaseCodePath(), b.getBaseCodePath());
+ assertEquals(a.getPath(), b.getPath());
+ assertEquals(a.getBaseApkPath(), b.getBaseApkPath());
assertArrayEquals(a.getSplitCodePaths(), b.getSplitCodePaths());
assertArrayEquals(a.getSplitRevisionCodes(), b.getSplitRevisionCodes());
assertArrayEquals(a.getSplitFlags(), b.getSplitFlags());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 56dddb0..4d8cc4647 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -533,7 +533,7 @@
arrayContaining("some.static.library", "some.other.static.library"));
assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L}));
assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage));
- assertThat(pkgSetting.getCodePath(), is(new File(createCodePath(packageName))));
+ assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName))));
assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345)));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index caa8ae5..3ce7a7d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -29,12 +29,10 @@
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.parsing.ApkLiteParseUtils;
-import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.os.FileUtils;
-import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -106,9 +104,9 @@
Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
assertEquals(1, packageDexMetadata.size());
- String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath());
+ String baseDexMetadata = packageDexMetadata.get(pkg.getBaseApkPath());
assertNotNull(baseDexMetadata);
- assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath()));
+ assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseApkPath()));
}
@Test
@@ -122,9 +120,9 @@
Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
assertEquals(2, packageDexMetadata.size());
- String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath());
+ String baseDexMetadata = packageDexMetadata.get(pkg.getBaseApkPath());
assertNotNull(baseDexMetadata);
- assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath()));
+ assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseApkPath()));
String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]);
assertNotNull(splitDexMetadata);
diff --git a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
index 056fa88..59cbd1c 100644
--- a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
+++ b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
@@ -22,8 +22,6 @@
import org.mockito.stubbing.Answer
import org.mockito.stubbing.Stubber
-// TODO(chiuwinson): Move this entire file to a shared utility module
-// TODO(b/135203078): De-dupe utils added for overlays vs package refactor
object MockitoUtils {
val ANSWER_THROWS = Answer<Any?> {
when (val name = it.method.name) {
@@ -64,7 +62,7 @@
fun whenever(mock: Unit) = Mockito.`when`(mock).thenAnswer { }
-inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit): T {
+inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit = {}): T {
val swappingAnswer = object : Answer<Any?> {
var delegate: Answer<*> = Answers.RETURNS_DEFAULTS
@@ -81,4 +79,5 @@
}
}
-inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit) = spyThrowOnUnmocked<T>(null, block)
+inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit = {}) =
+ spyThrowOnUnmocked<T>(null, block)
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 8644719..9e7226e7 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1086,12 +1086,18 @@
}
/**
- * Confirm the system user on automotive devices can use car categories
+ * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive
+ * devices can use car categories.
*/
@Test
- public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
+ public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
.thenReturn(true);
+ // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot
+ // obtain. Mocking out enforce permission call to ensure notifications can be created when
+ // permitted.
+ doNothing().when(mContext).enforceCallingPermission(
+ eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString());
List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
Notification.CATEGORY_CAR_WARNING,
Notification.CATEGORY_CAR_INFORMATION);
@@ -1114,7 +1120,6 @@
*/
@Test
public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
- mService.isSystemUid = false;
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
.thenReturn(false);
List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
@@ -1134,12 +1139,11 @@
}
/**
- * Confirm if a non-system user tries to use the car categories on a automotive device that
- * they will get a security exception
+ * Confirm if an application tries to use the car categories on a automotive device without the
+ * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown.
*/
@Test
- public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
- mService.isSystemUid = false;
+ public void testEnqueuedRestrictedNotifications_noPermission() throws Exception {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
.thenReturn(true);
List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 3c7206f..3430dbd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -44,6 +44,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
@@ -1556,6 +1557,49 @@
assertEquals(zenRule.getName(), ruleInConfig.name);
}
+ @Test
+ public void testRulesWithSameUri() {
+ Uri sharedUri = ZenModeConfig.toScheduleConditionId(new ScheduleInfo());
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProvider"),
+ sharedUri,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+ AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
+ new ComponentName("android", "ScheduleConditionProvider"),
+ sharedUri,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id2 = mZenModeHelperSpy.addAutomaticZenRule(zenRule2, "test");
+
+ Condition condition = new Condition(sharedUri, "", Condition.STATE_TRUE);
+ mZenModeHelperSpy.setAutomaticZenRuleState(sharedUri, condition);
+
+ for (ZenModeConfig.ZenRule rule : mZenModeHelperSpy.mConfig.automaticRules.values()) {
+ if (rule.id.equals(id)) {
+ assertNotNull(rule.condition);
+ assertTrue(rule.condition.state == Condition.STATE_TRUE);
+ }
+ if (rule.id.equals(id2)) {
+ assertNotNull(rule.condition);
+ assertTrue(rule.condition.state == Condition.STATE_TRUE);
+ }
+ }
+
+ condition = new Condition(sharedUri, "", Condition.STATE_FALSE);
+ mZenModeHelperSpy.setAutomaticZenRuleState(sharedUri, condition);
+
+ for (ZenModeConfig.ZenRule rule : mZenModeHelperSpy.mConfig.automaticRules.values()) {
+ if (rule.id.equals(id)) {
+ assertNotNull(rule.condition);
+ assertTrue(rule.condition.state == Condition.STATE_FALSE);
+ }
+ if (rule.id.equals(id2)) {
+ assertNotNull(rule.condition);
+ assertTrue(rule.condition.state == Condition.STATE_FALSE);
+ }
+ }
+ }
+
private void setupZenConfig() {
mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
new file mode 100644
index 0000000..f6c854e
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.server.slice;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+import com.android.server.slice.SliceManagerService.PackageMatchingCache;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Supplier;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class PackageMatchingCacheTest extends UiServiceTestCase {
+
+ private final Supplier<String> supplier = mock(Supplier.class);
+ private final PackageMatchingCache cache = new PackageMatchingCache(supplier);
+
+ @Test
+ public void testNulls() {
+ // Doesn't get for a null input
+ cache.matches(null);
+ verify(supplier, never()).get();
+
+ // Gets once valid input in sent.
+ cache.matches("");
+ verify(supplier).get();
+ }
+
+ @Test
+ public void testCaching() {
+ when(supplier.get()).thenReturn("ret.pkg");
+
+ assertTrue(cache.matches("ret.pkg"));
+ assertTrue(cache.matches("ret.pkg"));
+ assertTrue(cache.matches("ret.pkg"));
+
+ verify(supplier, times(1)).get();
+ }
+
+ @Test
+ public void testGetOnFailure() {
+ when(supplier.get()).thenReturn("ret.pkg");
+ assertTrue(cache.matches("ret.pkg"));
+
+ when(supplier.get()).thenReturn("other.pkg");
+ assertTrue(cache.matches("other.pkg"));
+ verify(supplier, times(2)).get();
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index cf1c36c..a443695 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -90,6 +90,8 @@
@Test
public void testAddPinCreatesPinned() throws RemoteException {
+ doReturn("pkg").when(mService).getDefaultHome(anyInt());
+
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
verify(mService, times(1)).createPinnedSlice(eq(maybeAddUserId(TEST_URI, 0)), anyString());
@@ -97,6 +99,8 @@
@Test
public void testRemovePinDestroysPinned() throws RemoteException {
+ doReturn("pkg").when(mService).getDefaultHome(anyInt());
+
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 09375db..89a0c7c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -73,7 +73,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
@@ -1671,8 +1670,6 @@
@Test
public void testCanTurnScreenOn() {
mStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- doReturn(true).when(mStack).checkKeyguardVisibility(
- same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean());
doReturn(true).when(mActivity).getTurnScreenOnFlag();
assertTrue(mActivity.canTurnScreenOn());
@@ -1681,8 +1678,6 @@
@Test
public void testFreeformWindowCantTurnScreenOn() {
mStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
- doReturn(true).when(mStack).checkKeyguardVisibility(
- same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean());
doReturn(true).when(mActivity).getTurnScreenOnFlag();
assertFalse(mActivity.canTurnScreenOn());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 4951658..a60f93a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1410,7 +1410,7 @@
new ActivityBuilder(mAtm).setTask(mTask).build();
new ActivityBuilder(mAtm).setTask(mTask).build();
doReturn(false).when(nonTopVisibleActivity).attachedToProcess();
- doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean());
+ doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleUnchecked();
doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
anyBoolean());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 7f90426..89a34cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -24,7 +24,6 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
import static android.os.Build.VERSION_CODES.P;
import static android.os.Build.VERSION_CODES.Q;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -762,13 +761,14 @@
window.mAttrs.screenOrientation, dc.getOrientation());
// ----------------------------
- // Test close-to-square display
+ // Test close-to-square display - should be handled in the same way
// ----------------------------
dc.mBaseDisplayHeight = dc.mBaseDisplayWidth;
dc.configureDisplayPolicy();
- assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.",
- SCREEN_ORIENTATION_USER, dc.getOrientation());
+ assertEquals(
+ "Screen orientation must be defined by the window even on close-to-square display.",
+ window.mAttrs.screenOrientation, dc.getOrientation());
}
@Test
@@ -823,7 +823,14 @@
final DisplayContent newDisplay = createNewDisplay();
final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+ final Task stack = mDisplayContent.getTopStack();
+ final ActivityRecord activity = stack.topRunningActivity();
+ doReturn(true).when(activity).shouldBeVisibleUnchecked();
+
final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
+ final Task stack1 = newDisplay.getTopStack();
+ final ActivityRecord activity1 = stack1.topRunningActivity();
+ doReturn(true).when(activity1).shouldBeVisibleUnchecked();
appWin.setHasSurface(true);
appWin1.setHasSurface(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 253fbae..58d994c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -44,6 +44,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -291,7 +292,8 @@
mRecentTasks.add(mTasks.get(1));
invocation.callRealMethod();
return null;
- }).when(mSupervisor).endActivityVisibilityUpdate();
+ }).when(mSupervisor).endActivityVisibilityUpdate(any(), anyInt(), anyBoolean(),
+ anyBoolean());
mTaskContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */, false /* notifyClients */);
@@ -1170,12 +1172,12 @@
() -> mAtm.setTaskWindowingModeSplitScreenPrimary(0, true));
assertSecurityException(expectCallable,
() -> mAtm.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
- assertSecurityException(expectCallable, () -> mAtm.getAllStackInfos());
+ assertSecurityException(expectCallable, () -> mAtm.getAllRootTaskInfos());
assertSecurityException(expectCallable,
- () -> mAtm.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
+ () -> mAtm.getRootTaskInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
assertSecurityException(expectCallable, () -> {
try {
- mAtm.getFocusedStackInfo();
+ mAtm.getFocusedRootTaskInfo();
} catch (RemoteException e) {
// Ignore
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 29081d3..edcf0d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -138,8 +138,6 @@
public void testFixedAspectRatioBoundsWithDecorInSquareDisplay() {
final int notchHeight = 100;
setUpApp(new TestDisplayContent.Builder(mAtm, 600, 800).setNotch(notchHeight).build());
- // Rotation is ignored so because the display size is close to square (700/600<1.333).
- assertTrue(mActivity.mDisplayContent.ignoreRotationForApps());
final Rect displayBounds = mActivity.mDisplayContent.getWindowConfiguration().getBounds();
final float aspectRatio = 1.2f;
@@ -163,23 +161,14 @@
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertFitted();
- // After the orientation of activity is changed, even display is not rotated, the aspect
- // ratio should be the same (bounds=[0, 0 - 600, 600], appBounds=[0, 100 - 600, 600]).
+ // After the orientation of activity is changed, the display is rotated, the aspect
+ // ratio should be the same (bounds=[100, 0 - 800, 583], appBounds=[100, 0 - 800, 583]).
assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */);
- // The notch is still on top.
- assertEquals(mActivity.getBounds().height(), appBounds.height() + notchHeight);
+ // The notch is no longer on top.
+ assertEquals(appBounds, mActivity.getBounds());
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertFitted();
-
- // Close-to-square display can rotate without being restricted by the requested orientation.
- // The notch becomes on the left side. The activity is horizontal centered in 100 ~ 800.
- // So the bounds and appBounds will be [200, 0 - 700, 600] (500x600) that is still fitted.
- // Left = 100 + (800 - 100 - 500) / 2 = 200.
- rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
- assertFitted();
- assertEquals(appBounds.left,
- notchHeight + (displayBounds.width() - notchHeight - appBounds.width()) / 2);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index eb7d9c2..6a29c5b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -534,11 +534,14 @@
doNothing().when(this).scheduleIdleTimeout(any());
// unit test version does not handle launch wake lock
doNothing().when(this).acquireLaunchWakelock();
- doReturn(mock(KeyguardController.class)).when(this).getKeyguardController();
mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
initialize();
+
+ final KeyguardController controller = getKeyguardController();
+ spyOn(controller);
+ doReturn(true).when(controller).checkKeyguardVisibility(any());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index e39b4bc..d37f3f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -17,17 +17,16 @@
package com.android.server.wm;
import android.graphics.Point;
-import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
-import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IScrollCaptureController;
import android.view.IWindow;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.window.ClientWindowFrames;
import com.android.internal.os.IResultReceiver;
@@ -38,10 +37,9 @@
}
@Override
- public void resized(Rect frame, Rect contentInsets, Rect visibleInsets,
- Rect stableInsets, boolean reportDraw, MergedConfiguration mergedConfig,
- Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
- DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException {
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars,
+ int displayId) throws RemoteException {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 38909f6..11eaf8c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -52,7 +52,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackInfo;
+import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.PictureInPictureParams;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -229,58 +229,32 @@
final Task task3 = createTask(stack3);
final ITaskOrganizer organizer = registerMockOrganizer();
- // First organizer is registered, verify a task appears when changing windowing mode
- stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
- verify(organizer, times(1))
+ // verify that tasks are appeared on registration
+ verify(organizer, times(3))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
assertTrue(stack.isOrganized());
// Now we replace the registration and1 verify the new organizer receives tasks
- // newly entering the windowing mode.
final ITaskOrganizer organizer2 = registerMockOrganizer();
- stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
- // One each for task and task2
- verify(organizer2, times(2))
+ verify(organizer2, times(3))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
verify(organizer2, times(0)).onTaskVanished(any());
// One for task
- verify(organizer).onTaskVanished(any());
+ verify(organizer, times(3)).onTaskVanished(any());
assertTrue(stack2.isOrganized());
// Now we unregister the second one, the first one should automatically be reregistered
// so we verify that it's now seeing changes.
mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
- verify(organizer, times(3))
+ verify(organizer, times(6))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
- verify(organizer2, times(2)).onTaskVanished(any());
-
- stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
- verify(organizer, times(4))
- .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
- verify(organizer2, times(2)).onTaskVanished(any());
- assertTrue(stack3.isOrganized());
- }
-
- @Test
- public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
- final ITaskOrganizer organizer = registerMockOrganizer();
-
- final Task stack = createStack();
- final Task task = createTask(stack);
- final Task task2 = createTask(stack);
- stack.setWindowingMode(WINDOWING_MODE_PINNED);
- verify(organizer, times(1))
- .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
-
- stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- verify(organizer, times(1)).onTaskVanished(any());
+ verify(organizer2, times(3)).onTaskVanished(any());
}
@Test
public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
final Task stack = createStack();
final Task task = createTask(stack);
- stack.setWindowingMode(WINDOWING_MODE_PINNED);
final ITaskOrganizer organizer = registerMockOrganizer();
verify(organizer, times(1))
@@ -301,9 +275,9 @@
removeGlobalMinSizeRestriction();
final Task stack = new TaskBuilder(mSupervisor)
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
- StackInfo info =
- mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
- assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken);
+ RootTaskInfo info =
+ mWm.mAtmService.getRootTaskInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
+ assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.token);
testTransaction(stack);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3106ca2..c18043f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -581,12 +581,10 @@
mWm.mResizingWindows.remove(win);
spyOn(win.mClient);
try {
- doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frame */,
- any() /* contentInsets */, any() /* visibleInsets */, any() /* stableInsets */,
+ doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */,
anyBoolean() /* reportDraw */, any() /* mergedConfig */,
- any() /* backDropFrame */, anyBoolean() /* forceLayout */,
- anyBoolean() /* alwaysConsumeSystemBars */, anyInt() /* displayId */,
- any() /* displayCutout */);
+ anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */,
+ anyInt() /* displayId */);
} catch (RemoteException ignored) {
}
win.reportResized();
diff --git a/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl
new file mode 100644
index 0000000..50bbf4c
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.telecom;
+
+/*
+ * Adapter interface for using DeviceIdleController, since the PowerWhitelistManager is not
+ * directly accessible in the SYSTEM process.
+ */
+interface IDeviceIdleControllerAdapter {
+ void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle,
+ String reason);
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl
similarity index 60%
copy from packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
copy to telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl
index e65f19d..b560106 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
+++ b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,17 +14,14 @@
* limitations under the License.
*/
-package com.android.keyguard.dagger;
+package com.android.internal.telecom;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import com.android.internal.telecom.IDeviceIdleControllerAdapter;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface ContainerView {
+/*
+ * Interface used to retrieve services that are only accessible via LocalService in the SYSTEM
+ * process.
+ */
+interface IInternalServiceRetriever {
+ IDeviceIdleControllerAdapter getDeviceIdleController();
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl
new file mode 100644
index 0000000..eda0f5b
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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.telecom;
+
+import com.android.internal.telecom.ITelecomService;
+import com.android.internal.telecom.IInternalServiceRetriever;
+
+/*
+ * Internal interface for getting an instance of the ITelecomService for external publication.
+ * Allows the TelecomLoaderService to pass additional dependencies required for creation.
+ */
+interface ITelecomLoader {
+ ITelecomService createTelecomService(IInternalServiceRetriever retriever);
+}
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 943d783..a53ea16 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -28,7 +28,6 @@
"flickertestapplib",
"flickerlib",
"truth-prebuilt",
- "app-helpers-core",
"launcher-helper-lib",
"launcher-aosp-tapl"
],
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt
deleted file mode 100644
index 7147577..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.server.wm.flicker.helpers
-
-import android.app.Instrumentation
-import android.support.test.launcherhelper.ILauncherStrategy
-import com.android.server.wm.flicker.StandardAppHelper
-
-abstract class FlickerAppHelper(
- instr: Instrumentation,
- launcherName: String,
- launcherStrategy: ILauncherStrategy
-) : StandardAppHelper(instr, sFlickerPackage, launcherName, launcherStrategy) {
- companion object {
- var sFlickerPackage = "com.android.server.wm.flicker.testapp"
- }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index c1b7657..f4de36e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -30,7 +30,7 @@
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
-) : FlickerAppHelper(instr, launcherName, launcherStrategy) {
+) : StandardAppHelper(instr, launcherName, launcherStrategy) {
open fun openIME(device: UiDevice) {
val editText = device.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index d10bb1e..0572a78 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -28,7 +28,7 @@
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
-) : FlickerAppHelper(instr, "PipApp", launcherStrategy) {
+) : StandardAppHelper(instr, "PipApp", launcherStrategy) {
fun clickEnterPipButton(device: UiDevice) {
val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"))
Assert.assertNotNull("Pip button not found, this usually happens when the device " +
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt
index 7d70812..98e05d5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.LayersAssertion
import com.android.server.wm.flicker.dsl.WmAssertion
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index afadb58..acd141a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -18,7 +18,7 @@
import android.view.Surface
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.focusChanges
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 0ca1508..99218c2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -20,7 +20,7 @@
import android.view.Surface
import com.android.server.wm.flicker.NonRotationTestBase.Companion.SCREENSHOT_LAYER
import com.android.server.wm.flicker.RotationTestBase
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.WindowUtils
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
index c5e48d9..3b5e669 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
@@ -19,7 +19,7 @@
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.focusChanges
import com.android.server.wm.flicker.helpers.exitSplitScreen
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
index 91211ca..abf41a1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
@@ -24,7 +24,7 @@
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import com.android.server.wm.flicker.FlickerTestBase
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.ImeAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
index 5c7dcd9..87c8633 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
@@ -19,7 +19,7 @@
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.exitSplitScreen
diff --git a/tests/SilkFX/res/layout/activity_glass.xml b/tests/SilkFX/res/layout/activity_glass.xml
index a7b76bd..aa09f27 100644
--- a/tests/SilkFX/res/layout/activity_glass.xml
+++ b/tests/SilkFX/res/layout/activity_glass.xml
@@ -41,7 +41,16 @@
app:layout_constraintBottom_toTopOf="@+id/bottomPanel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
+ app:layout_constraintTop_toTopOf="parent">
+ <TextView
+ android:id="@+id/textOverlay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="18dp"
+ android:layout_gravity="center"
+ android:textColor="#ffffff"
+ android:text="Lorem Ipsum dolor sit amet." />
+ </com.android.test.silkfx.materials.GlassView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottomPanel"
@@ -90,7 +99,7 @@
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:max="150"
- android:progress="20"
+ android:progress="40"
app:layout_constraintBottom_toTopOf="@+id/materialOpacityTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
@@ -118,7 +127,7 @@
android:layout_marginEnd="12dp"
android:layout_marginBottom="24dp"
android:max="100"
- android:progress="5"
+ android:progress="15"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
@@ -141,7 +150,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="8dp"
- android:text="Material Opacity"
+ android:text="Soft light Opacity"
android:textColor="@android:color/white"
app:layout_constraintBottom_toTopOf="@+id/materialOpacity"
app:layout_constraintStart_toStartOf="parent" />
@@ -219,6 +228,19 @@
app:layout_constraintStart_toEndOf="@+id/background2"
android:src="@drawable/background3" />
+ <Button
+ android:id="@+id/pickImage"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:scaleType="centerCrop"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onPickImageClick"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background3"
+ android:text="Pick file" />
+
<Switch
android:id="@+id/lightMaterialSwitch"
android:layout_width="wrap_content"
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt
index 72b342c..dde245f 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt
@@ -16,6 +16,7 @@
package com.android.test.silkfx.materials
import android.app.Activity
+import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
@@ -46,8 +47,14 @@
lateinit var scrimOpacityValue: TextView
lateinit var blurRadiusValue: TextView
lateinit var zoomValue: TextView
+ lateinit var textOverlay: TextView
- lateinit var background: Bitmap
+ var background: Bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+ set(value) {
+ field = value
+ backgroundView.setImageBitmap(background)
+ materialView.backgroundBitmap = background
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -68,10 +75,9 @@
scrimOpacityValue = requireViewById(R.id.scrimOpacityValue)
blurRadiusValue = requireViewById(R.id.blurRadiusValue)
zoomValue = requireViewById(R.id.zoomValue)
+ textOverlay = requireViewById(R.id.textOverlay)
background = BitmapFactory.decodeResource(resources, R.drawable.background1)
- backgroundView.setImageBitmap(background)
- materialView.backgroundBitmap = background
blurRadiusSeekBar.setOnSeekBarChangeListener(this)
materialOpacitySeekBar.setOnSeekBarChangeListener(this)
@@ -86,6 +92,7 @@
lightMaterialSwitch.setOnCheckedChangeListener { _, isChecked ->
materialView.color = if (isChecked) Color.WHITE else Color.BLACK
+ textOverlay.setTextColor(if (isChecked) Color.BLACK else Color.WHITE)
}
}
@@ -116,6 +123,11 @@
}
}
+ override fun onStop() {
+ super.onStop()
+ materialView.resetGyroOffsets()
+ }
+
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
@@ -128,7 +140,23 @@
}
background = BitmapFactory.decodeResource(resources, resource)
- backgroundView.setImageBitmap(background)
- materialView.backgroundBitmap = background
+ }
+
+ fun onPickImageClick(view: View) {
+ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
+ addCategory(Intent.CATEGORY_OPENABLE)
+ type = "image/*"
+ }
+ startActivityForResult(intent, 0)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (resultCode === RESULT_OK) {
+ data?.data?.also {
+ contentResolver.openFileDescriptor(it, "r").let {
+ background = BitmapFactory.decodeFileDescriptor(it?.fileDescriptor)
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt
index 6079768..71175847 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt
@@ -25,23 +25,83 @@
import android.graphics.Color
import android.graphics.Outline
import android.graphics.Paint
+import android.graphics.RadialGradient
import android.graphics.Rect
import android.graphics.Shader
+import android.hardware.Sensor
+import android.hardware.SensorEvent
+import android.hardware.SensorEventListener
+import android.hardware.SensorManager
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
+import android.widget.FrameLayout
+import com.android.internal.graphics.ColorUtils
import com.android.test.silkfx.R
+import kotlin.math.sin
+import kotlin.math.sqrt
-class GlassView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) {
+class GlassView(context: Context, attributeSet: AttributeSet) : FrameLayout(context, attributeSet) {
- var noise = BitmapFactory.decodeResource(resources, R.drawable.noise)
- var materialPaint = Paint()
- var scrimPaint = Paint()
- var noisePaint = Paint()
- var blurPaint = Paint()
+ private val textureTranslationMultiplier = 200f
- val src = Rect()
- val dst = Rect()
+ private var gyroXRotation = 0f
+ private var gyroYRotation = 0f
+
+ private var noise = BitmapFactory.decodeResource(resources, R.drawable.noise)
+ private var materialPaint = Paint()
+ private var scrimPaint = Paint()
+ private var noisePaint = Paint()
+ private var blurPaint = Paint()
+
+ private val src = Rect()
+ private val dst = Rect()
+
+ private val sensorManager = context.getSystemService(SensorManager::class.java)
+ private val sensorListener = object : SensorEventListener {
+
+ // Constant to convert nanoseconds to seconds.
+ private val NS2S = 1.0f / 1000000000.0f
+ private val EPSILON = 0.000001f
+ private var timestamp: Float = 0f
+
+ override fun onSensorChanged(event: SensorEvent?) {
+ // This timestep's delta rotation to be multiplied by the current rotation
+ // after computing it from the gyro sample data.
+ if (timestamp != 0f && event != null) {
+ val dT = (event.timestamp - timestamp) * NS2S
+ // Axis of the rotation sample, not normalized yet.
+ var axisX: Float = event.values[0]
+ var axisY: Float = event.values[1]
+ var axisZ: Float = event.values[2]
+
+ // Calculate the angular speed of the sample
+ val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ)
+
+ // Normalize the rotation vector if it's big enough to get the axis
+ // (that is, EPSILON should represent your maximum allowable margin of error)
+ if (omegaMagnitude > EPSILON) {
+ axisX /= omegaMagnitude
+ axisY /= omegaMagnitude
+ axisZ /= omegaMagnitude
+ }
+
+ // Integrate around this axis with the angular speed by the timestep
+ // in order to get a delta rotation from this sample over the timestep
+ // We will convert this axis-angle representation of the delta rotation
+ // into a quaternion before turning it into the rotation matrix.
+ val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f
+ val sinThetaOverTwo: Float = sin(thetaOverTwo)
+ gyroXRotation += sinThetaOverTwo * axisX
+ gyroYRotation += sinThetaOverTwo * axisY
+
+ invalidate()
+ }
+ timestamp = event?.timestamp?.toFloat() ?: 0f
+ }
+
+ override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { }
+ }
var backgroundBitmap: Bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
set(value) {
@@ -97,6 +157,7 @@
}
init {
+ setWillNotDraw(false)
materialPaint.blendMode = BlendMode.SOFT_LIGHT
noisePaint.blendMode = BlendMode.SOFT_LIGHT
noisePaint.shader = BitmapShader(noise, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
@@ -112,12 +173,25 @@
clipToOutline = true
}
+ override fun onAttachedToWindow() {
+ sensorManager?.getSensorList(Sensor.TYPE_GYROSCOPE)?.firstOrNull().let {
+ sensorManager?.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_GAME)
+ }
+ }
+
+ override fun onDetachedFromWindow() {
+ sensorManager?.unregisterListener(sensorListener)
+ }
+
override fun onDraw(canvas: Canvas?) {
- src.set(-width/2, -height/2, width/2, height/2)
+ src.set(-width / 2, -height / 2, width / 2, height / 2)
src.scale(1.0f + zoom)
val centerX = left + width / 2
val centerY = top + height / 2
- src.set(src.left + centerX, src.top + centerY, src.right + centerX, src.bottom + centerY)
+ val textureXOffset = (textureTranslationMultiplier * gyroYRotation).toInt()
+ val textureYOffset = (textureTranslationMultiplier * gyroXRotation).toInt()
+ src.set(src.left + centerX + textureXOffset, src.top + centerY + textureYOffset,
+ src.right + centerX + textureXOffset, src.bottom + centerY + textureYOffset)
dst.set(0, 0, width, height)
canvas?.drawBitmap(backgroundBitmap, src, dst, blurPaint)
@@ -125,4 +199,10 @@
canvas?.drawRect(dst, noisePaint)
canvas?.drawRect(dst, scrimPaint)
}
+
+ fun resetGyroOffsets() {
+ gyroXRotation = 0f
+ gyroYRotation = 0f
+ invalidate()
+ }
}
\ No newline at end of file
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index d0742c7..3f5c673 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -144,6 +144,7 @@
@Deprecated public static class WifiConfiguration.GroupCipher {
field @Deprecated public static final int CCMP = 3; // 0x3
+ field @Deprecated public static final int GCMP_128 = 7; // 0x7
field @Deprecated public static final int GCMP_256 = 5; // 0x5
field @Deprecated public static final int SMS4 = 6; // 0x6
field @Deprecated public static final int TKIP = 2; // 0x2
@@ -173,6 +174,7 @@
@Deprecated public static class WifiConfiguration.PairwiseCipher {
field @Deprecated public static final int CCMP = 2; // 0x2
+ field @Deprecated public static final int GCMP_128 = 5; // 0x5
field @Deprecated public static final int GCMP_256 = 3; // 0x3
field @Deprecated public static final int NONE = 0; // 0x0
field @Deprecated public static final int SMS4 = 4; // 0x4
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index eff64a3..c3e573c 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -449,6 +449,7 @@
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public boolean is60GHzBandSupported();
method public boolean isApMacRandomizationSupported();
method public boolean isConnectedMacRandomizationSupported();
method @Deprecated public boolean isDeviceToDeviceRttSupported();
@@ -651,6 +652,7 @@
field public static final int WIFI_BAND_5_GHZ = 2; // 0x2
field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4
field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6
+ field public static final int WIFI_BAND_60_GHZ = 16; // 0x10
field public static final int WIFI_BAND_6_GHZ = 8; // 0x8
field public static final int WIFI_BAND_BOTH = 3; // 0x3
field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index e493789..b3ed8ac 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -118,6 +118,8 @@
boolean is6GHzBandSupported();
+ boolean is60GHzBandSupported();
+
boolean isWifiStandardSupported(int standard);
DhcpInfo getDhcpInfo();
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 656444e..02b7a42 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -301,9 +301,16 @@
*/
public static final int SMS4 = 4;
+ /**
+ * AES in Galois/Counter Mode with a 128-bit integrity key
+ */
+ public static final int GCMP_128 = 5;
+
+
public static final String varName = "pairwise";
- public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4" };
+ public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4",
+ "GCMP_128" };
}
/**
@@ -345,13 +352,17 @@
* SMS4 cipher for WAPI
*/
public static final int SMS4 = 6;
+ /**
+ * AES in Galois/Counter Mode with a 128-bit integrity key
+ */
+ public static final int GCMP_128 = 7;
public static final String varName = "group";
public static final String[] strings =
{ /* deprecated */ "WEP40", /* deprecated */ "WEP104",
"TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256",
- "SMS4" };
+ "SMS4", "GCMP_128" };
}
/**
@@ -498,8 +509,10 @@
allowedProtocols.set(WifiConfiguration.Protocol.RSN);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
requirePmf = true;
break;
@@ -508,7 +521,9 @@
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+ allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
+ allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
// Note: allowedSuiteBCiphers bitset will be set by the service once the
@@ -519,8 +534,10 @@
allowedProtocols.set(WifiConfiguration.Protocol.RSN);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
requirePmf = true;
break;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b28b902..c76f4a6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2407,6 +2407,8 @@
public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support
/** @hide */
public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI
+ /** @hide */
+ public static final long WIFI_FEATURE_INFRA_60G = 0x4000000000L; // 60 GHz Band Support
/** @hide */
public static final long WIFI_FEATURE_FILS_SHA256 = 0x4000000000L; // FILS-SHA256
@@ -2569,6 +2571,21 @@
}
/**
+ * Check if the chipset supports the 60GHz frequency band.
+ *
+ * @return {@code true} if supported, {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ public boolean is60GHzBandSupported() {
+ try {
+ return mService.is60GHzBandSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Check if the chipset supports 6GHz band.
* @return {@code true} if supported, {@code false} otherwise.
*/
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index aa69963..e992c83 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -176,7 +176,7 @@
mWapiEnterpriseConfig = null;
mIsNetworkUntrusted = false;
mPriorityGroup = 0;
- mIsEnhancedMacRandomizationEnabled = true;
+ mIsEnhancedMacRandomizationEnabled = false;
}
/**
@@ -409,11 +409,12 @@
* Suggested networks will never use the device (factory) MAC address to associate to the
* network - instead they use a locally generated random MAC address. This method controls
* the strategy for generating the random MAC address:
- * <li> Persisted MAC randomization (false): generates the MAC address from a secret seed
- * and information from the Wi-Fi configuration (SSID or Passpoint profile). That means that
- * the same generated MAC address will be used for each subsequent association. </li>
- * <li> Enhanced MAC randomization (true - the default): periodically generates a new MAC
- * address new connections. Under this option, the randomized MAC address should change
+ * <li> Persisted MAC randomization (false - the default): generates the MAC address from a
+ * secret seed and information from the Wi-Fi configuration (SSID or Passpoint profile).
+ * This means that the same generated MAC address will be used for each subsequent
+ * association. </li>
+ * <li> Enhanced MAC randomization (true): periodically generates a new MAC
+ * address for new connections. Under this option, the randomized MAC address should change
* if the suggestion is removed and then added back. </li>
*
* @param enabled {@code true} to periodically change the randomized MAC address.
@@ -731,6 +732,8 @@
+ "suggestion with Passpoint configuration");
}
wifiConfiguration = buildWifiConfigurationForPasspoint();
+ mPasspointConfiguration.setEnhancedMacRandomizationEnabled(
+ mIsEnhancedMacRandomizationEnabled);
} else {
if (mSsid == null) {
throw new IllegalStateException("setSsid should be invoked for suggestion");
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 94771ac..a68d7e2 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -68,7 +68,9 @@
/** @hide */
public static final int WIFI_BAND_INDEX_6_GHZ = 3;
/** @hide */
- public static final int WIFI_BAND_COUNT = 4;
+ public static final int WIFI_BAND_INDEX_60_GHZ = 4;
+ /** @hide */
+ public static final int WIFI_BAND_COUNT = 5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -76,7 +78,8 @@
WIFI_BAND_INDEX_24_GHZ,
WIFI_BAND_INDEX_5_GHZ,
WIFI_BAND_INDEX_5_GHZ_DFS_ONLY,
- WIFI_BAND_INDEX_6_GHZ})
+ WIFI_BAND_INDEX_6_GHZ,
+ WIFI_BAND_INDEX_60_GHZ})
public @interface WifiBandIndex {}
/** no band specified; use channel list instead */
@@ -89,6 +92,8 @@
public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 1 << WIFI_BAND_INDEX_5_GHZ_DFS_ONLY;
/** 6 GHz band */
public static final int WIFI_BAND_6_GHZ = 1 << WIFI_BAND_INDEX_6_GHZ;
+ /** 60 GHz band */
+ public static final int WIFI_BAND_60_GHZ = 1 << WIFI_BAND_INDEX_60_GHZ;
/**
* Combination of bands
@@ -113,6 +118,12 @@
/** 2.4 GHz band and 5 GHz band; with DFS channels and 6 GHz */
public static final int WIFI_BAND_24_5_WITH_DFS_6_GHZ =
WIFI_BAND_BOTH_WITH_DFS | WIFI_BAND_6_GHZ;
+ /** @hide */
+ public static final int WIFI_BAND_24_5_6_60_GHZ =
+ WIFI_BAND_24_5_6_GHZ | WIFI_BAND_60_GHZ;
+ /** @hide */
+ public static final int WIFI_BAND_24_5_WITH_DFS_6_60_GHZ =
+ WIFI_BAND_24_5_6_60_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -127,7 +138,10 @@
WIFI_BAND_BOTH_WITH_DFS,
WIFI_BAND_6_GHZ,
WIFI_BAND_24_5_6_GHZ,
- WIFI_BAND_24_5_WITH_DFS_6_GHZ})
+ WIFI_BAND_24_5_WITH_DFS_6_GHZ,
+ WIFI_BAND_60_GHZ,
+ WIFI_BAND_24_5_6_60_GHZ,
+ WIFI_BAND_24_5_WITH_DFS_6_60_GHZ})
public @interface WifiBand {}
/**
@@ -179,7 +193,10 @@
* @hide
*/
public static boolean isFullBandScan(@WifiBand int bandScanned, boolean excludeDfs) {
- return (bandScanned | WIFI_BAND_6_GHZ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0))
+ // 5GHz DFS channel is part of 5GHz, mark 5GHz scanned as well.
+ if ((bandScanned & WIFI_BAND_5_GHZ_DFS_ONLY) != 0) bandScanned |= WIFI_BAND_5_GHZ;
+ return (bandScanned | WIFI_BAND_6_GHZ | WIFI_BAND_60_GHZ
+ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0))
== WIFI_BAND_ALL;
}
@@ -571,6 +588,19 @@
}
}
+ /** {@hide} */
+ public void addResults(@NonNull ScanData s) {
+ mBandScanned |= s.mBandScanned;
+ mFlags |= s.mFlags;
+ addResults(s.getResults());
+ }
+
+ /** {@hide} */
+ public boolean isFullBandScanResults() {
+ return (mBandScanned & WifiScanner.WIFI_BAND_24_GHZ) != 0
+ && (mBandScanned & WifiScanner.WIFI_BAND_5_GHZ) != 0;
+ }
+
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index d1d1780..61a6e16 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -444,6 +444,11 @@
private boolean mIsMacRandomizationEnabled = true;
/**
+ * Whether this passpoint configuration should use enhanced MAC randomization.
+ */
+ private boolean mIsEnhancedMacRandomizationEnabled = false;
+
+ /**
* Indicates if the end user has expressed an explicit opinion about the
* meteredness of this network, such as through the Settings app.
* This value is one of {@link #METERED_OVERRIDE_NONE}, {@link #METERED_OVERRIDE_METERED},
@@ -481,6 +486,20 @@
}
/**
+ * This setting is only applicable if MAC randomization is enabled.
+ * If set to true, the framework will periodically generate new MAC addresses for new
+ * connections.
+ * If set to false (the default), the framework will use the same locally generated MAC address
+ * for connections to this passpoint configuration.
+ * @param enabled true to use enhanced MAC randomization, false to use persistent MAC
+ * randomization.
+ * @hide
+ */
+ public void setEnhancedMacRandomizationEnabled(boolean enabled) {
+ mIsEnhancedMacRandomizationEnabled = enabled;
+ }
+
+ /**
* Sets the metered override setting for this Passpoint configuration.
*
* @param meteredOverride One of the values in {@link MeteredOverride}
@@ -531,6 +550,19 @@
}
/**
+ * When MAC randomization is enabled, this indicates whether enhanced MAC randomization or
+ * persistent MAC randomization will be used for connections to this Passpoint network.
+ * If true, the MAC address used for connections will periodically change. Otherwise, the same
+ * locally generated MAC will be used for all connections to this passpoint configuration.
+ *
+ * @return true for enhanced MAC randomization enabled. False for disabled.
+ * @hide
+ */
+ public boolean isEnhancedMacRandomizationEnabled() {
+ return mIsEnhancedMacRandomizationEnabled;
+ }
+
+ /**
* Constructor for creating PasspointConfiguration with default values.
*/
public PasspointConfiguration() {}
@@ -574,6 +606,7 @@
mCarrierId = source.mCarrierId;
mIsAutojoinEnabled = source.mIsAutojoinEnabled;
mIsMacRandomizationEnabled = source.mIsMacRandomizationEnabled;
+ mIsEnhancedMacRandomizationEnabled = source.mIsEnhancedMacRandomizationEnabled;
mMeteredOverride = source.mMeteredOverride;
}
@@ -606,6 +639,7 @@
dest.writeInt(mCarrierId);
dest.writeBoolean(mIsAutojoinEnabled);
dest.writeBoolean(mIsMacRandomizationEnabled);
+ dest.writeBoolean(mIsEnhancedMacRandomizationEnabled);
dest.writeInt(mMeteredOverride);
}
@@ -639,6 +673,7 @@
&& mCarrierId == that.mCarrierId
&& mIsAutojoinEnabled == that.mIsAutojoinEnabled
&& mIsMacRandomizationEnabled == that.mIsMacRandomizationEnabled
+ && mIsEnhancedMacRandomizationEnabled == that.mIsEnhancedMacRandomizationEnabled
&& mMeteredOverride == that.mMeteredOverride
&& (mServiceFriendlyNames == null ? that.mServiceFriendlyNames == null
: mServiceFriendlyNames.equals(that.mServiceFriendlyNames));
@@ -651,7 +686,7 @@
mSubscriptionExpirationTimeMillis, mUsageLimitUsageTimePeriodInMinutes,
mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes,
mServiceFriendlyNames, mCarrierId, mIsAutojoinEnabled, mIsMacRandomizationEnabled,
- mMeteredOverride);
+ mIsEnhancedMacRandomizationEnabled, mMeteredOverride);
}
@Override
@@ -707,6 +742,7 @@
builder.append("CarrierId:" + mCarrierId);
builder.append("IsAutojoinEnabled:" + mIsAutojoinEnabled);
builder.append("mIsMacRandomizationEnabled:" + mIsMacRandomizationEnabled);
+ builder.append("mIsEnhancedMacRandomizationEnabled:" + mIsEnhancedMacRandomizationEnabled);
builder.append("mMeteredOverride:" + mMeteredOverride);
return builder.toString();
}
@@ -815,6 +851,7 @@
config.mCarrierId = in.readInt();
config.mIsAutojoinEnabled = in.readBoolean();
config.mIsMacRandomizationEnabled = in.readBoolean();
+ config.mIsEnhancedMacRandomizationEnabled = in.readBoolean();
config.mMeteredOverride = in.readInt();
return config;
}
diff --git a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java b/wifi/java/android/net/wifi/nl80211/NativeScanResult.java
index a8e9999..35cf45f 100644
--- a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java
+++ b/wifi/java/android/net/wifi/nl80211/NativeScanResult.java
@@ -225,6 +225,15 @@
* BSS capability bit (see IEEE Std 802.11: 9.4.1.4): Immediate Block Ack.
*/
public static final int BSS_CAPABILITY_IMMEDIATE_BLOCK_ACK = 0x1 << 15;
+ /**
+ * BSS capability bit (see IEEE Std 802.11: 9.4.1.4): DMG ESS.
+ * In DMG bits 0 and 1 are parsed together, where ESS=0x3 and IBSS=0x1
+ */
+ public static final int BSS_CAPABILITY_DMG_ESS = 0x3;
+ /**
+ * BSS capability bit (see IEEE Std 802.11: 9.4.1.4): DMG IBSS.
+ */
+ public static final int BSS_CAPABILITY_DMG_IBSS = 0x1;
/**
* Returns the capabilities of the AP repseresented by this scan result as advertised in the
diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
index 3175e45..fb58d3f 100644
--- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
+++ b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
@@ -1048,6 +1048,7 @@
* {@link WifiScanner#WIFI_BAND_5_GHZ},
* {@link WifiScanner#WIFI_BAND_5_GHZ_DFS_ONLY},
* {@link WifiScanner#WIFI_BAND_6_GHZ}
+ * {@link WifiScanner.WIFI_BAND_60_GHZ}
* @return frequencies vector of valid frequencies (MHz), or an empty array for error.
* @throws IllegalArgumentException if band is not recognized.
*/
@@ -1071,6 +1072,9 @@
case WifiScanner.WIFI_BAND_6_GHZ:
result = mWificond.getAvailable6gChannels();
break;
+ case WifiScanner.WIFI_BAND_60_GHZ:
+ result = mWificond.getAvailable60gChannels();
+ break;
default:
throw new IllegalArgumentException("unsupported band " + band);
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index abb9ce6..668d238 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -682,15 +682,15 @@
}
/**
- * Verify that the macRandomizationSetting defaults to RANDOMIZATION_ENHANCED and could be set
- * to RANDOMIZATION_PERSISTENT.
+ * Verify that the macRandomizationSetting defaults to RANDOMIZATION_PERSISTENT and could be set
+ * to RANDOMIZATION_ENHANCED.
*/
@Test
public void testWifiNetworkSuggestionBuilderSetMacRandomization() {
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
.setSsid(TEST_SSID)
.build();
- assertEquals(WifiConfiguration.RANDOMIZATION_ENHANCED,
+ assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT,
suggestion.wifiConfiguration.macRandomizationSetting);
suggestion = new WifiNetworkSuggestion.Builder()
@@ -709,6 +709,31 @@
}
/**
+ * Verify that the builder creates the appropriate PasspointConfiguration according to the
+ * enhanced MAC randomization setting.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderSetMacRandomizationPasspoint() {
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .build();
+ assertEquals(false, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setIsEnhancedMacRandomizationEnabled(false)
+ .build();
+ assertEquals(false, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setIsEnhancedMacRandomizationEnabled(true)
+ .build();
+ assertEquals(true, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+ }
+
+ /**
* Check that parcel marshalling/unmarshalling works
*/
@Test
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 8270d64..badcf52 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -186,6 +186,7 @@
assertFalse(config.validateForR2());
assertTrue(config.isAutojoinEnabled());
assertTrue(config.isMacRandomizationEnabled());
+ assertFalse(config.isEnhancedMacRandomizationEnabled());
assertTrue(config.getMeteredOverride() == METERED_OVERRIDE_NONE);
}