summaryrefslogtreecommitdiff
path: root/services/core
diff options
context:
space:
mode:
Diffstat (limited to 'services/core')
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java3
-rw-r--r--services/core/java/com/android/server/VpnManagerService.java5
-rw-r--r--services/core/java/com/android/server/apphibernation/AppHibernationService.java76
-rw-r--r--services/core/java/com/android/server/apphibernation/HibernationStateDiskStore.java1
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java20
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java35
-rw-r--r--services/core/java/com/android/server/recoverysystem/RecoverySystemService.java123
7 files changed, 206 insertions, 57 deletions
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 6c18cdea51fa..d561ab96c365 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -821,8 +821,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final IBinder cbBinder = callback.asBinder();
final VcnStatusCallbackInfo cbInfo =
- new VcnStatusCallbackInfo(
- subGroup, callback, opPkgName, mDeps.getBinderCallingUid());
+ new VcnStatusCallbackInfo(subGroup, callback, opPkgName, callingUid);
try {
cbBinder.linkToDeath(cbInfo, 0 /* flags */);
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 56aabc208027..d756c1ffd00f 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -352,7 +352,10 @@ public class VpnManagerService extends IVpnManager.Stub {
@Override
public void startLegacyVpn(VpnProfile profile) {
int user = UserHandle.getUserId(mDeps.getCallingUid());
- final LinkProperties egress = mCm.getActiveLinkProperties();
+ // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID),
+ // the code might not work well since getActiveNetwork might return null if the uid is
+ // blocked by NetworkPolicyManagerService.
+ final LinkProperties egress = mCm.getLinkProperties(mCm.getActiveNetwork());
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index b3373d0bb536..351231f34c4b 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -69,6 +69,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -101,6 +102,7 @@ public final class AppHibernationService extends SystemService {
private final Map<String, GlobalLevelState> mGlobalHibernationStates = new ArrayMap<>();
private final HibernationStateDiskStore<GlobalLevelState> mGlobalLevelHibernationDiskStore;
private final Injector mInjector;
+ private final Executor mBackgroundExecutor;
@VisibleForTesting
boolean mIsServiceEnabled;
@@ -126,6 +128,7 @@ public final class AppHibernationService extends SystemService {
mIActivityManager = injector.getActivityManager();
mUserManager = injector.getUserManager();
mGlobalLevelHibernationDiskStore = injector.getGlobalLevelDiskStore();
+ mBackgroundExecutor = injector.getBackgroundExecutor();
mInjector = injector;
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
@@ -147,11 +150,13 @@ public final class AppHibernationService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_BOOT_COMPLETED) {
- List<GlobalLevelState> states =
- mGlobalLevelHibernationDiskStore.readHibernationStates();
- synchronized (mLock) {
- initializeGlobalHibernationStates(states);
- }
+ mBackgroundExecutor.execute(() -> {
+ List<GlobalLevelState> states =
+ mGlobalLevelHibernationDiskStore.readHibernationStates();
+ synchronized (mLock) {
+ initializeGlobalHibernationStates(states);
+ }
+ });
}
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mIsServiceEnabled = isAppHibernationEnabled();
@@ -170,16 +175,15 @@ public final class AppHibernationService extends SystemService {
* @return true if package is hibernating for the user
*/
boolean isHibernatingForUser(String packageName, int userId) {
- if (!checkHibernationEnabled("isHibernatingForUser")) {
+ String methodName = "isHibernatingForUser";
+ if (!checkHibernationEnabled(methodName)) {
return false;
}
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
- userId = handleIncomingUser(userId, "isHibernating");
- if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
- Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user "
- + userId);
+ userId = handleIncomingUser(userId, methodName);
+ if (!checkUserStatesExist(userId, methodName)) {
return false;
}
synchronized (mLock) {
@@ -225,16 +229,15 @@ public final class AppHibernationService extends SystemService {
* @param isHibernating new hibernation state
*/
void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
- if (!checkHibernationEnabled("setHibernatingForUser")) {
+ String methodName = "setHibernatingForUser";
+ if (!checkHibernationEnabled(methodName)) {
return;
}
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
- userId = handleIncomingUser(userId, "setHibernating");
- if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
- Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user "
- + userId);
+ userId = handleIncomingUser(userId, methodName);
+ if (!checkUserStatesExist(userId, methodName)) {
return;
}
synchronized (mLock) {
@@ -298,16 +301,15 @@ public final class AppHibernationService extends SystemService {
*/
@NonNull List<String> getHibernatingPackagesForUser(int userId) {
ArrayList<String> hibernatingPackages = new ArrayList<>();
- if (!checkHibernationEnabled("getHibernatingPackagesForUser")) {
+ String methodName = "getHibernatingPackagesForUser";
+ if (!checkHibernationEnabled(methodName)) {
return hibernatingPackages;
}
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
- userId = handleIncomingUser(userId, "getHibernatingPackagesForUser");
- if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
- Slog.w(TAG, "Attempt to get hibernating packages for a stopped or nonexistent user "
- + userId);
+ userId = handleIncomingUser(userId, methodName);
+ if (!checkUserStatesExist(userId, methodName)) {
return hibernatingPackages;
}
synchronized (mLock) {
@@ -477,10 +479,15 @@ public final class AppHibernationService extends SystemService {
HibernationStateDiskStore<UserLevelState> diskStore =
mInjector.getUserLevelDiskStore(userId);
mUserDiskStores.put(userId, diskStore);
- List<UserLevelState> storedStates = diskStore.readHibernationStates();
- synchronized (mLock) {
- initializeUserHibernationStates(userId, storedStates);
- }
+ mBackgroundExecutor.execute(() -> {
+ List<UserLevelState> storedStates = diskStore.readHibernationStates();
+ synchronized (mLock) {
+ // Ensure user hasn't stopped in the time to execute.
+ if (mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ initializeUserHibernationStates(userId, storedStates);
+ }
+ }
+ });
}
@Override
@@ -550,6 +557,20 @@ public final class AppHibernationService extends SystemService {
}
}
+ private boolean checkUserStatesExist(int userId, String methodName) {
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ Slog.e(TAG, String.format(
+ "Attempt to call %s on stopped or nonexistent user %d", methodName, userId));
+ return false;
+ }
+ if (!mUserStates.contains(userId)) {
+ Slog.w(TAG, String.format(
+ "Attempt to call %s before states have been read from disk", methodName));
+ return false;
+ }
+ return true;
+ }
+
private boolean checkHibernationEnabled(String methodName) {
if (!mIsServiceEnabled) {
Slog.w(TAG, String.format("Attempted to call %s on unsupported device.", methodName));
@@ -720,6 +741,8 @@ public final class AppHibernationService extends SystemService {
UserManager getUserManager();
+ Executor getBackgroundExecutor();
+
HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore();
HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId);
@@ -758,6 +781,11 @@ public final class AppHibernationService extends SystemService {
}
@Override
+ public Executor getBackgroundExecutor() {
+ return mScheduledExecutorService;
+ }
+
+ @Override
public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() {
File dir = new File(Environment.getDataSystemDirectory(), HIBERNATION_DIR_NAME);
return new HibernationStateDiskStore<>(
diff --git a/services/core/java/com/android/server/apphibernation/HibernationStateDiskStore.java b/services/core/java/com/android/server/apphibernation/HibernationStateDiskStore.java
index c83659d2ff56..24cf43339847 100644
--- a/services/core/java/com/android/server/apphibernation/HibernationStateDiskStore.java
+++ b/services/core/java/com/android/server/apphibernation/HibernationStateDiskStore.java
@@ -109,6 +109,7 @@ class HibernationStateDiskStore<T> {
* @return the parsed list of hibernation states, null if file does not exist
*/
@Nullable
+ @WorkerThread
List<T> readHibernationStates() {
synchronized (this) {
if (!mHibernationFile.exists()) {
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index b355730c6450..6776f49b7d8f 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -91,16 +91,19 @@ class HostClipboardMonitor implements Runnable {
return bits;
}
- private void openPipe() {
+ private boolean openPipe() {
try {
- mPipe = new RandomAccessFile(PIPE_DEVICE, "rw");
- mPipe.write(createOpenHandshake());
- } catch (IOException e) {
+ final RandomAccessFile pipe = new RandomAccessFile(PIPE_DEVICE, "rw");
try {
- if (mPipe != null) mPipe.close();
- } catch (IOException ee) {}
- mPipe = null;
+ pipe.write(createOpenHandshake());
+ mPipe = pipe;
+ return true;
+ } catch (IOException ignore) {
+ pipe.close();
+ }
+ } catch (IOException ignore) {
}
+ return false;
}
public HostClipboardMonitor(HostClipboardCallback cb) {
@@ -114,8 +117,7 @@ class HostClipboardMonitor implements Runnable {
// There's no guarantee that QEMU pipes will be ready at the moment
// this method is invoked. We simply try to get the pipe open and
// retry on failure indefinitely.
- while (mPipe == null) {
- openPipe();
+ while ((mPipe == null) && !openPipe()) {
Thread.sleep(100);
}
int size = mPipe.readInt();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index aecac7576bcf..46c80e7c44e3 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -56,7 +56,9 @@ import static android.net.NetworkIdentity.OEM_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_FOREGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_MASK;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_USER_EXEMPTED;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
@@ -4636,8 +4638,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
newBlockedReasons |= (mRestrictBackground ? BLOCKED_METERED_REASON_DATA_SAVER : 0);
newBlockedReasons |= (isDenied ? BLOCKED_METERED_REASON_USER_RESTRICTED : 0);
- newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
- newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
+ newAllowedReasons |= (isSystem(uid) ? ALLOWED_METERED_REASON_SYSTEM : 0);
+ newAllowedReasons |= (isForeground ? ALLOWED_METERED_REASON_FOREGROUND : 0);
newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0);
if (LOGV) {
@@ -4711,18 +4713,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Dispatch changed rule to existing listeners.
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
+ }
- final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
- & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
- uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
- & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
- uidBlockedState.updateEffectiveBlockedReasons();
- if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
- mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
- uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons)
- .sendToTarget();
- }
+ final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
+ & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
+ uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
+ & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
+ if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
+ mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
+ uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons)
+ .sendToTarget();
}
}
@@ -5870,12 +5872,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return;
}
if ((allowedReasons & ALLOWED_REASON_SYSTEM) != 0) {
- effectiveBlockedReasons = BLOCKED_REASON_NONE;
+ effectiveBlockedReasons = (blockedReasons & ALLOWED_METERED_REASON_MASK);
+ }
+ if ((allowedReasons & ALLOWED_METERED_REASON_SYSTEM) != 0) {
+ effectiveBlockedReasons = (blockedReasons & ~ALLOWED_METERED_REASON_MASK);
}
if ((allowedReasons & ALLOWED_REASON_FOREGROUND) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE;
effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY;
+ }
+ if ((allowedReasons & ALLOWED_METERED_REASON_FOREGROUND) != 0) {
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_USER_RESTRICTED;
}
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index beebb3145018..0a6772bd8f6a 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -21,11 +21,13 @@ import static android.os.UserHandle.USER_SYSTEM;
import android.annotation.IntDef;
import android.content.Context;
import android.content.IntentSender;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.boot.V1_0.IBootControl;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Binder;
+import android.os.Environment;
import android.os.IRecoverySystem;
import android.os.IRecoverySystemProgressListener;
import android.os.PowerManager;
@@ -52,6 +54,7 @@ import libcore.io.IoUtils;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.FileWriter;
import java.io.IOException;
@@ -87,6 +90,12 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
+ static final String REQUEST_LSKF_TIMESTAMP_PREF_SUFFIX = "_request_lskf_timestamp";
+ static final String REQUEST_LSKF_COUNT_PREF_SUFFIX = "_request_lskf_count";
+
+ static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp";
+ static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count";
+
private final Injector mInjector;
private final Context mContext;
@@ -127,7 +136,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
*/
@IntDef({ ROR_NEED_PREPARATION,
ROR_SKIP_PREPARATION_AND_NOTIFY,
- ROR_SKIP_PREPARATION_NOT_NOTIFY })
+ ROR_SKIP_PREPARATION_NOT_NOTIFY})
private @interface ResumeOnRebootActionsOnRequest {}
/**
@@ -139,7 +148,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
private @interface ResumeOnRebootActionsOnClear {}
/**
- * The error code for reboots initiated by resume on reboot clients.
+ * The error codes for reboots initiated by resume on reboot clients.
*/
private static final int REBOOT_ERROR_NONE = 0;
private static final int REBOOT_ERROR_UNKNOWN = 1;
@@ -156,11 +165,64 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE})
private @interface ResumeOnRebootRebootErrorCode {}
+ /**
+ * Manages shared preference, i.e. the storage used for metrics reporting.
+ */
+ public static class PreferencesManager {
+ private static final String METRICS_DIR = "recovery_system";
+ private static final String METRICS_PREFS_FILE = "RecoverySystemMetricsPrefs.xml";
+
+ protected final SharedPreferences mSharedPreferences;
+ private final File mMetricsPrefsFile;
+
+ PreferencesManager(Context context) {
+ File prefsDir = new File(Environment.getDataSystemCeDirectory(USER_SYSTEM),
+ METRICS_DIR);
+ mMetricsPrefsFile = new File(prefsDir, METRICS_PREFS_FILE);
+ mSharedPreferences = context.getSharedPreferences(mMetricsPrefsFile, 0);
+ }
+
+ /** Reads the value of a given key with type long. **/
+ public long getLong(String key, long defaultValue) {
+ return mSharedPreferences.getLong(key, defaultValue);
+ }
+
+ /** Reads the value of a given key with type int. **/
+ public int getInt(String key, int defaultValue) {
+ return mSharedPreferences.getInt(key, defaultValue);
+ }
+
+ /** Stores the value of a given key with type long. **/
+ public void putLong(String key, long value) {
+ mSharedPreferences.edit().putLong(key, value).commit();
+ }
+
+ /** Stores the value of a given key with type int. **/
+ public void putInt(String key, int value) {
+ mSharedPreferences.edit().putInt(key, value).commit();
+ }
+
+ /** Increments the value of a given key with type int. **/
+ public synchronized void incrementIntKey(String key, int defaultInitialValue) {
+ int oldValue = getInt(key, defaultInitialValue);
+ putInt(key, oldValue + 1);
+ }
+
+ /** Delete the preference file and cleanup all metrics storage. **/
+ public void deletePrefsFile() {
+ if (!mMetricsPrefsFile.delete()) {
+ Slog.w(TAG, "Failed to delete metrics prefs");
+ }
+ }
+ }
+
static class Injector {
protected final Context mContext;
+ protected final PreferencesManager mPrefs;
Injector(Context context) {
mContext = context;
+ mPrefs = new PreferencesManager(context);
}
public Context getContext() {
@@ -236,6 +298,14 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
return -1;
}
+ public PreferencesManager getMetricsPrefs() {
+ return mPrefs;
+ }
+
+ public long getCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
public void reportRebootEscrowPreparationMetrics(int uid,
@ResumeOnRebootActionsOnRequest int requestResult, int requestedClientCount) {
FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_PREPARATION_REPORTED, uid,
@@ -414,7 +484,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(android.Manifest.permission.REBOOT)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller must have " + android.Manifest.permission.RECOVERY
+ " or " + android.Manifest.permission.REBOOT + " for resume on reboot.");
}
@@ -427,6 +497,12 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
pendingRequestCount = mCallerPendingRequest.size();
}
+ // Save the timestamp and request count for new ror request
+ PreferencesManager prefs = mInjector.getMetricsPrefs();
+ prefs.putLong(packageName + REQUEST_LSKF_TIMESTAMP_PREF_SUFFIX,
+ mInjector.getCurrentTimeMillis());
+ prefs.incrementIntKey(packageName + REQUEST_LSKF_COUNT_PREF_SUFFIX, 0);
+
mInjector.reportRebootEscrowPreparationMetrics(uid, requestResult, pendingRequestCount);
}
@@ -486,15 +562,31 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
}
private void reportMetricsOnPreparedForReboot() {
+ long currentTimestamp = mInjector.getCurrentTimeMillis();
+
List<String> preparedClients;
synchronized (this) {
preparedClients = new ArrayList<>(mCallerPreparedForReboot);
}
+ // Save the timestamp & lskf capture count for lskf capture
+ PreferencesManager prefs = mInjector.getMetricsPrefs();
+ prefs.putLong(LSKF_CAPTURED_TIMESTAMP_PREF, currentTimestamp);
+ prefs.incrementIntKey(LSKF_CAPTURED_COUNT_PREF, 0);
+
for (String packageName : preparedClients) {
int uid = mInjector.getUidFromPackageName(packageName);
+
+ int durationSeconds = -1;
+ long requestLskfTimestamp = prefs.getLong(
+ packageName + REQUEST_LSKF_TIMESTAMP_PREF_SUFFIX, -1);
+ if (requestLskfTimestamp != -1 && currentTimestamp > requestLskfTimestamp) {
+ durationSeconds = (int) (currentTimestamp - requestLskfTimestamp) / 1000;
+ }
+ Slog.i(TAG, String.format("Reporting lskf captured, lskf capture takes %d seconds for"
+ + " package %s", durationSeconds, packageName));
mInjector.reportRebootEscrowLskfCapturedMetrics(uid, preparedClients.size(),
- -1 /* duration */);
+ durationSeconds);
}
}
@@ -541,6 +633,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
Slog.w(TAG, "Missing packageName when clearing lskf.");
return false;
}
+ // TODO(179105110) Clear the RoR metrics for the given packageName.
@ResumeOnRebootActionsOnClear int action = updateRoRPreparationStateOnClear(packageName);
switch (action) {
@@ -659,10 +752,23 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
preparedClientCount = mCallerPreparedForReboot.size();
}
- // TODO(b/179105110) report the true value of duration and counts
+ long currentTimestamp = mInjector.getCurrentTimeMillis();
+ int durationSeconds = -1;
+ PreferencesManager prefs = mInjector.getMetricsPrefs();
+ long lskfCapturedTimestamp = prefs.getLong(LSKF_CAPTURED_TIMESTAMP_PREF, -1);
+ if (lskfCapturedTimestamp != -1 && currentTimestamp > lskfCapturedTimestamp) {
+ durationSeconds = (int) (currentTimestamp - lskfCapturedTimestamp) / 1000;
+ }
+
+ int requestCount = prefs.getInt(packageName + REQUEST_LSKF_COUNT_PREF_SUFFIX, -1);
+ int lskfCapturedCount = prefs.getInt(LSKF_CAPTURED_COUNT_PREF, -1);
+
+ Slog.i(TAG, String.format("Reporting reboot with lskf, package name %s, client count %d,"
+ + " request count %d, lskf captured count %d, duration since lskf captured"
+ + " %d seconds.", packageName, preparedClientCount, requestCount,
+ lskfCapturedCount, durationSeconds));
mInjector.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount,
- 1 /* request count */, slotSwitch, serverBased,
- -1 /* duration */, 1 /* lskf capture count */);
+ requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount);
}
private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
@@ -673,6 +779,9 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
return false;
}
+ // Clear the metrics prefs after a successful RoR reboot.
+ mInjector.getMetricsPrefs().deletePrefsFile();
+
PowerManager pm = mInjector.getPowerManager();
pm.reboot(reason);
return true;