BootReceiver.java revision 492c6ed5b64cfdd72dc270e6b848025a26eff724
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 23d40df335e4c0df972720271a84277077f168f65Dan Egnor * Copyright (C) 2009 The Android Open Source Project 33d40df335e4c0df972720271a84277077f168f65Dan Egnor * 43d40df335e4c0df972720271a84277077f168f65Dan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 53d40df335e4c0df972720271a84277077f168f65Dan Egnor * you may not use this file except in compliance with the License. 63d40df335e4c0df972720271a84277077f168f65Dan Egnor * You may obtain a copy of the License at 73d40df335e4c0df972720271a84277077f168f65Dan Egnor * 83d40df335e4c0df972720271a84277077f168f65Dan Egnor * http://www.apache.org/licenses/LICENSE-2.0 93d40df335e4c0df972720271a84277077f168f65Dan Egnor * 103d40df335e4c0df972720271a84277077f168f65Dan Egnor * Unless required by applicable law or agreed to in writing, software 113d40df335e4c0df972720271a84277077f168f65Dan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 123d40df335e4c0df972720271a84277077f168f65Dan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d40df335e4c0df972720271a84277077f168f65Dan Egnor * See the License for the specific language governing permissions and 143d40df335e4c0df972720271a84277077f168f65Dan Egnor * limitations under the License. 153d40df335e4c0df972720271a84277077f168f65Dan Egnor */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 193d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.content.BroadcastReceiver; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 23492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnorimport android.content.SharedPreferences; 243d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.os.Build; 253d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.os.DropBoxManager; 26492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnorimport android.os.FileObserver; 273d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.os.FileUtils; 281af33d0ddc2f50ade146e4d48e2feb6f1d553427Doug Zongkerimport android.os.RecoverySystem; 293d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.os.SystemProperties; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 313d40df335e4c0df972720271a84277077f168f65Dan Egnorimport android.util.Log; 323d40df335e4c0df972720271a84277077f168f65Dan Egnor 333d40df335e4c0df972720271a84277077f168f65Dan Egnorimport java.io.File; 343d40df335e4c0df972720271a84277077f168f65Dan Egnorimport java.io.IOException; 353d40df335e4c0df972720271a84277077f168f65Dan Egnor 363d40df335e4c0df972720271a84277077f168f65Dan Egnor/** 373d40df335e4c0df972720271a84277077f168f65Dan Egnor * Performs a number of miscellaneous, non-system-critical actions 383d40df335e4c0df972720271a84277077f168f65Dan Egnor * after the system has finished booting. 393d40df335e4c0df972720271a84277077f168f65Dan Egnor */ 403d40df335e4c0df972720271a84277077f168f65Dan Egnorpublic class BootReceiver extends BroadcastReceiver { 413d40df335e4c0df972720271a84277077f168f65Dan Egnor private static final String TAG = "BootReceiver"; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 43492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor // Negative to read the *last* 64K of the file (per FileUtils.readTextFile) 4442471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor private static final int LOG_SIZE = -65536; 4542471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor 46492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor private static final File TOMBSTONE_DIR = new File("/data/tombstones"); 47492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor 48492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor // Keep a reference to the observer so the finalizer doesn't disable it. 49492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor private static FileObserver sTombstoneObserver = null; 50492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 523d40df335e4c0df972720271a84277077f168f65Dan Egnor public void onReceive(Context context, Intent intent) { 533d40df335e4c0df972720271a84277077f168f65Dan Egnor try { 543d40df335e4c0df972720271a84277077f168f65Dan Egnor logBootEvents(context); 553d40df335e4c0df972720271a84277077f168f65Dan Egnor } catch (Exception e) { 563d40df335e4c0df972720271a84277077f168f65Dan Egnor Log.e(TAG, "Can't log boot events", e); 573d40df335e4c0df972720271a84277077f168f65Dan Egnor } 583d40df335e4c0df972720271a84277077f168f65Dan Egnor 593d40df335e4c0df972720271a84277077f168f65Dan Egnor try { 603d40df335e4c0df972720271a84277077f168f65Dan Egnor RecoverySystem.handleAftermath(); 613d40df335e4c0df972720271a84277077f168f65Dan Egnor } catch (Exception e) { 623d40df335e4c0df972720271a84277077f168f65Dan Egnor Log.e(TAG, "Can't handle recovery aftermath", e); 633d40df335e4c0df972720271a84277077f168f65Dan Egnor } 643d40df335e4c0df972720271a84277077f168f65Dan Egnor 653d40df335e4c0df972720271a84277077f168f65Dan Egnor try { 663d40df335e4c0df972720271a84277077f168f65Dan Egnor // Start the load average overlay, if activated 673d40df335e4c0df972720271a84277077f168f65Dan Egnor ContentResolver res = context.getContentResolver(); 683d40df335e4c0df972720271a84277077f168f65Dan Egnor if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) { 693d40df335e4c0df972720271a84277077f168f65Dan Egnor Intent loadavg = new Intent(context, com.android.server.LoadAverageService.class); 703d40df335e4c0df972720271a84277077f168f65Dan Egnor context.startService(loadavg); 713d40df335e4c0df972720271a84277077f168f65Dan Egnor } 723d40df335e4c0df972720271a84277077f168f65Dan Egnor } catch (Exception e) { 733d40df335e4c0df972720271a84277077f168f65Dan Egnor Log.e(TAG, "Can't start load average service", e); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 77492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor private void logBootEvents(Context ctx) throws IOException { 78492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); 79492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor final SharedPreferences prefs = ctx.getSharedPreferences("log_files", Context.MODE_PRIVATE); 80492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor final String props = new StringBuilder() 81492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append("Build: ").append(Build.FINGERPRINT).append("\n") 82492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append("Hardware: ").append(Build.BOARD).append("\n") 83492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append("Bootloader: ").append(Build.BOOTLOADER).append("\n") 84492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append("Radio: ").append(Build.RADIO).append("\n") 85492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append("Kernel: ") 86492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n")) 87492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor .toString(); 883d40df335e4c0df972720271a84277077f168f65Dan Egnor 89492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor if (db == null || prefs == null) return; 903d40df335e4c0df972720271a84277077f168f65Dan Egnor 913d40df335e4c0df972720271a84277077f168f65Dan Egnor if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) { 923d40df335e4c0df972720271a84277077f168f65Dan Egnor String now = Long.toString(System.currentTimeMillis()); 933d40df335e4c0df972720271a84277077f168f65Dan Egnor SystemProperties.set("ro.runtime.firstboot", now); 94492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor db.addText("SYSTEM_BOOT", props); 95492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, "/proc/last_kmsg", "SYSTEM_LAST_KMSG"); 96492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, "/cache/recovery/log", "SYSTEM_RECOVERY_LOG"); 97492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_console", "APANIC_CONSOLE"); 98492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_threads", "APANIC_THREADS"); 993d40df335e4c0df972720271a84277077f168f65Dan Egnor } else { 100492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor db.addText("SYSTEM_RESTART", props); 101492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor } 102492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor 103492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor // Scan existing tombstones (in case any new ones appeared) 104492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); 105492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) { 106492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, tombstoneFiles[i].getPath(), "SYSTEM_TOMBSTONE"); 1073d40df335e4c0df972720271a84277077f168f65Dan Egnor } 1083d40df335e4c0df972720271a84277077f168f65Dan Egnor 109492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor // Start watching for new tombstone files; will record them as they occur. 110492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor // This gets registered with the singleton file observer thread. 111492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CLOSE_WRITE) { 112492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor @Override 113492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor public void onEvent(int event, String path) { 114492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor try { 115492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor String filename = new File(TOMBSTONE_DIR, path).getPath(); 116492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor addFileToDropBox(db, prefs, props, filename, "SYSTEM_TOMBSTONE"); 117492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor } catch (IOException e) { 118492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor Log.e(TAG, "Can't log tombstone", e); 119492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor } 120492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor } 121492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor }; 122492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor 123492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor sTombstoneObserver.startWatching(); 1243d40df335e4c0df972720271a84277077f168f65Dan Egnor } 1253d40df335e4c0df972720271a84277077f168f65Dan Egnor 126492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor private static void addFileToDropBox( 127492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor DropBoxManager db, SharedPreferences prefs, 128492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor String headers, String filename, String tag) throws IOException { 129492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor if (!db.isTagEnabled(tag)) return; // Logging disabled 1303d40df335e4c0df972720271a84277077f168f65Dan Egnor 1313d40df335e4c0df972720271a84277077f168f65Dan Egnor File file = new File(filename); 1323d40df335e4c0df972720271a84277077f168f65Dan Egnor long fileTime = file.lastModified(); 1333d40df335e4c0df972720271a84277077f168f65Dan Egnor if (fileTime <= 0) return; // File does not exist 1343d40df335e4c0df972720271a84277077f168f65Dan Egnor 135492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor long lastTime = prefs.getLong(filename, 0); 1363d40df335e4c0df972720271a84277077f168f65Dan Egnor if (lastTime == fileTime) return; // Already logged this particular file 137492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor prefs.edit().putLong(filename, fileTime).commit(); 13842471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor 139492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor StringBuilder report = new StringBuilder(headers).append("\n"); 140492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor report.append(FileUtils.readTextFile(file, LOG_SIZE, "[[TRUNCATED]]\n")); 14142471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor db.addText(tag, report.toString()); 142492c6ed5b64cfdd72dc270e6b848025a26eff724Dan Egnor Log.i(TAG, "Logging " + filename + " to DropBox (" + tag + ")"); 1433d40df335e4c0df972720271a84277077f168f65Dan Egnor } 1443d40df335e4c0df972720271a84277077f168f65Dan Egnor} 145