diff options
Diffstat (limited to 'services/core')
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; |