1fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey/* 2fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Copyright (C) 2017 The Android Open Source Project 3fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * 4fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * you may not use this file except in compliance with the License. 6fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * You may obtain a copy of the License at 7fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * 8fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * 10fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * See the License for the specific language governing permissions and 14fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * limitations under the License. 15fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 16fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 17fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeypackage com.android.server; 18fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 19fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.content.ContentResolver; 20fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.content.Context; 219f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkeyimport android.os.Build; 228231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkeyimport android.os.Environment; 231bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkeyimport android.os.FileUtils; 24fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.os.RecoverySystem; 25fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.os.SystemClock; 26fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.os.SystemProperties; 27fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.os.UserHandle; 28fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.provider.Settings; 29fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.text.format.DateUtils; 30fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.util.ExceptionUtils; 31bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkeyimport android.util.Log; 32fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.util.MathUtils; 33fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.util.Slog; 34fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport android.util.SparseArray; 35fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 36fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeyimport com.android.internal.util.ArrayUtils; 37bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkeyimport com.android.server.pm.PackageManagerService; 38fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 391bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkeyimport java.io.File; 40d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey 41fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey/** 42fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Utilities to help rescue the system from crash loops. Callers are expected to 43fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * report boot events and persistent app crashes, and if they happen frequently 44fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * enough this class will slowly escalate through several rescue operations 45fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * before finally rebooting and prompting the user if they want to wipe data as 46fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * a last resort. 47fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * 48fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * @hide 49fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 50fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkeypublic class RescueParty { 51fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final String TAG = "RescueParty"; 52fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 53bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey private static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue"; 549f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue"; 55fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final String PROP_RESCUE_LEVEL = "sys.rescue_level"; 56fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count"; 57fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final String PROP_RESCUE_BOOT_START = "sys.rescue_boot_start"; 58fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 59fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final int LEVEL_NONE = 0; 60fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final int LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1; 61fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final int LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2; 62fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3; 63fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final int LEVEL_FACTORY_RESET = 4; 64fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 65fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** Threshold for boot loops */ 66fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static final Threshold sBoot = new BootThreshold(); 67fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** Threshold for app crash loops */ 68fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static SparseArray<Threshold> sApps = new SparseArray<>(); 69fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 709f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey private static boolean isDisabled() { 71bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey // Check if we're explicitly enabled for testing 728231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) { 73bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey return false; 74bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey } 75bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey 76cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey // We're disabled on all engineering devices 77d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey if (Build.IS_ENG) { 78d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey Slog.v(TAG, "Disabled because of eng build"); 79d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey return true; 80d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } 81cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey 82cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey // We're disabled on userdebug devices connected over USB, since that's 83cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey // a decent signal that someone is actively trying to debug the device, 84cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey // or that it's in a lab environment. 85d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey if (Build.IS_USERDEBUG && isUsbActive()) { 86d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey Slog.v(TAG, "Disabled because of active USB connection"); 87d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey return true; 88cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey } 89cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey 90cdee83a6147bf1601424d5451c30f0dfb8d0e2a6Jeff Sharkey // One last-ditch check 91d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey if (SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false)) { 92d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey Slog.v(TAG, "Disabled because of manual property"); 93d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey return true; 94d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } 95d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey 96d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey return false; 979f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey } 989f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey 99fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 100fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Take note of a boot event. If we notice too many of these events 101fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * happening in rapid succession, we'll send out a rescue party. 102fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 103fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public static void noteBoot(Context context) { 1049f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey if (isDisabled()) return; 105fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (sBoot.incrementAndTest()) { 106fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey sBoot.reset(); 107fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey incrementRescueLevel(sBoot.uid); 108fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey executeRescueLevel(context); 109fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 110fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 111fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 112fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 113fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Take note of a persistent app crash. If we notice too many of these 114fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * events happening in rapid succession, we'll send out a rescue party. 115fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 116fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public static void notePersistentAppCrash(Context context, int uid) { 1179f1fc2d78743ce2d4de546c80d4f93c2ffcc8804Jeff Sharkey if (isDisabled()) return; 118fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Threshold t = sApps.get(uid); 119fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (t == null) { 120fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey t = new AppThreshold(uid); 121fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey sApps.put(uid, t); 122fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 123fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (t.incrementAndTest()) { 124fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey t.reset(); 125fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey incrementRescueLevel(t.uid); 126fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey executeRescueLevel(context); 127fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 128fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 129fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 130fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 131fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Check if we're currently attempting to reboot for a factory reset. 132fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 133fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public static boolean isAttemptingFactoryReset() { 134fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE) == LEVEL_FACTORY_RESET; 135fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 136fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 137fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 138fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Escalate to the next rescue level. After incrementing the level you'll 139fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * probably want to call {@link #executeRescueLevel(Context)}. 140fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 141fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static void incrementRescueLevel(int triggerUid) { 142fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey final int level = MathUtils.constrain( 143fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE) + 1, 144fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey LEVEL_NONE, LEVEL_FACTORY_RESET); 145fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey SystemProperties.set(PROP_RESCUE_LEVEL, Integer.toString(level)); 146fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 147fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey EventLogTags.writeRescueLevel(level, triggerUid); 148bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey PackageManagerService.logCriticalInfo(Log.WARN, "Incremented rescue level to " 149bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey + levelToString(level) + " triggered by UID " + triggerUid); 150fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 151fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 152fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 153fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Called when {@code SettingsProvider} has been published, which is a good 154fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * opportunity to reset any settings depending on our rescue level. 155fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 156fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public static void onSettingsProviderPublished(Context context) { 157fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey executeRescueLevel(context); 158fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 159fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 160fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static void executeRescueLevel(Context context) { 161fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey final int level = SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE); 162fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (level == LEVEL_NONE) return; 163fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 164fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Slog.w(TAG, "Attempting rescue level " + levelToString(level)); 165fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey try { 166fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey executeRescueLevelInternal(context, level); 167fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey EventLogTags.writeRescueSuccess(level); 168bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey PackageManagerService.logCriticalInfo(Log.DEBUG, 169bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey "Finished rescue level " + levelToString(level)); 170fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } catch (Throwable t) { 171bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey final String msg = ExceptionUtils.getCompleteMessage(t); 172bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey EventLogTags.writeRescueFailure(level, msg); 173bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey PackageManagerService.logCriticalInfo(Log.ERROR, 174bc9caa1a2a38e23f7a6b61bcda81b5759e45ec66Jeff Sharkey "Failed rescue level " + levelToString(level) + ": " + msg); 175fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 176fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 177fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 178fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static void executeRescueLevelInternal(Context context, int level) throws Exception { 179fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey switch (level) { 180fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: 181fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS); 182fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey break; 183fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: 184fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES); 185fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey break; 186fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: 187fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS); 188fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey break; 189fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_FACTORY_RESET: 190fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey RecoverySystem.rebootPromptAndWipeUserData(context, TAG); 191fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey break; 192fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 193fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 194fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 195fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static void resetAllSettings(Context context, int mode) throws Exception { 196fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // Try our best to reset all settings possible, and once finished 197fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // rethrow any exception that we encountered 198fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Exception res = null; 199fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey final ContentResolver resolver = context.getContentResolver(); 200fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey try { 201fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Settings.Global.resetToDefaultsAsUser(resolver, null, mode, UserHandle.USER_SYSTEM); 202d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } catch (Throwable t) { 203d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey res = new RuntimeException("Failed to reset global settings", t); 204fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 2058231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey for (int userId : getAllUserIds()) { 206fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey try { 207fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId); 208d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } catch (Throwable t) { 209d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey res = new RuntimeException("Failed to reset secure settings for " + userId, t); 210fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 211fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 212fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (res != null) { 213fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey throw res; 214fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 215fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 216fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 217fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 218fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Threshold that can be triggered if a number of events occur within a 219fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * window of time. 220fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 221fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private abstract static class Threshold { 222fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public abstract int getCount(); 223fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public abstract void setCount(int count); 224fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public abstract long getStart(); 225fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public abstract void setStart(long start); 226fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 227fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private final int uid; 228fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private final int triggerCount; 229fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private final long triggerWindow; 230fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 231fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public Threshold(int uid, int triggerCount, long triggerWindow) { 232fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey this.uid = uid; 233fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey this.triggerCount = triggerCount; 234fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey this.triggerWindow = triggerWindow; 235fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 236fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 237fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public void reset() { 238fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey setCount(0); 239fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey setStart(0); 240fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 241fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 242fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 243fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * @return if this threshold has been triggered 244fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 245fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public boolean incrementAndTest() { 246fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey final long now = SystemClock.elapsedRealtime(); 247fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey final long window = now - getStart(); 248fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey if (window > triggerWindow) { 249fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey setCount(1); 250fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey setStart(now); 251fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return false; 252fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } else { 253fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey int count = getCount() + 1; 254fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey setCount(count); 255fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey EventLogTags.writeRescueNote(uid, count, window); 256fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Slog.w(TAG, "Noticed " + count + " events for UID " + uid + " in last " 257fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey + (window / 1000) + " sec"); 258fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return (count >= triggerCount); 259fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 260fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 261fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 262fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 263fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 264fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Specialization of {@link Threshold} for monitoring boot events. It stores 265fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * counters in system properties for robustness. 266fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 267fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static class BootThreshold extends Threshold { 268fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public BootThreshold() { 269fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // We're interested in 5 events in any 300 second period; this 270fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // window is super relaxed because booting can take a long time if 271fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // forced to dexopt things. 272fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey super(android.os.Process.ROOT_UID, 5, 300 * DateUtils.SECOND_IN_MILLIS); 273fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 274fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 275fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override 276fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public int getCount() { 277fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return SystemProperties.getInt(PROP_RESCUE_BOOT_COUNT, 0); 278fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 279fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 280fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override 281fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public void setCount(int count) { 282fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey SystemProperties.set(PROP_RESCUE_BOOT_COUNT, Integer.toString(count)); 283fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 284fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 285fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override 286fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public long getStart() { 287fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return SystemProperties.getLong(PROP_RESCUE_BOOT_START, 0); 288fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 289fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 290fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override 291fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public void setStart(long start) { 292fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey SystemProperties.set(PROP_RESCUE_BOOT_START, Long.toString(start)); 293fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 294fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 295fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 296fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey /** 297fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * Specialization of {@link Threshold} for monitoring app crashes. It stores 298fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey * counters in memory. 299fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey */ 300fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static class AppThreshold extends Threshold { 301fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private int count; 302fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private long start; 303fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 304fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey public AppThreshold(int uid) { 305fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // We're interested in 5 events in any 30 second period; apps crash 306fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey // pretty quickly so we can keep a tight leash on them. 307fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey super(uid, 5, 30 * DateUtils.SECOND_IN_MILLIS); 308fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 309fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 310fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override public int getCount() { return count; } 311fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override public void setCount(int count) { this.count = count; } 312fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override public long getStart() { return start; } 313fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey @Override public void setStart(long start) { this.start = start; } 314fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 315fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 3168231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey private static int[] getAllUserIds() { 317fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey int[] userIds = { UserHandle.USER_SYSTEM }; 318fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey try { 3198231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey for (File file : FileUtils.listFilesOrEmpty(Environment.getDataSystemDeDirectory())) { 3208231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey try { 3218231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey final int userId = Integer.parseInt(file.getName()); 3228231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey if (userId != UserHandle.USER_SYSTEM) { 3238231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey userIds = ArrayUtils.appendInt(userIds, userId); 3248231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey } 3258231146d4ede7f0c0767da2bfdea58745611417cJeff Sharkey } catch (NumberFormatException ignored) { 326fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 327fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 328fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } catch (Throwable t) { 329fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey Slog.w(TAG, "Trouble discovering users", t); 330fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 331fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey return userIds; 332fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 333fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey 334d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey /** 335d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey * Hacky test to check if the device has an active USB connection, which is 3361bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkey * a good proxy for someone doing local development work. 337d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey */ 338d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey private static boolean isUsbActive() { 339d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey try { 3401bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkey final String state = FileUtils 3411bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkey .readTextFile(new File("/sys/class/android_usb/android0/state"), 128, ""); 3421bec44836ed6b29e128849b7be34dc7b2a214e76Jeff Sharkey return "CONFIGURED".equals(state.trim()); 343d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } catch (Throwable t) { 344d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey Slog.w(TAG, "Failed to determine if device was on USB", t); 345d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey return false; 346d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } 347d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey } 348d9574c7bbf23ca282b93b1297e936a3d2e98e78aJeff Sharkey 349fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey private static String levelToString(int level) { 350fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey switch (level) { 351fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_NONE: return "NONE"; 352fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: return "RESET_SETTINGS_UNTRUSTED_DEFAULTS"; 353fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: return "RESET_SETTINGS_UNTRUSTED_CHANGES"; 354fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: return "RESET_SETTINGS_TRUSTED_DEFAULTS"; 355fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey case LEVEL_FACTORY_RESET: return "FACTORY_RESET"; 356fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey default: return Integer.toString(level); 357fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 358fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey } 359fe6f85cac9e823fd33a134f7129fdf7310703293Jeff Sharkey} 360