@SmallTest public void testStressMemoryPropertyConsistency() throws Exception { for (int i = 0; i < 100; ++i) { SystemProperties.set(KEY, Long.toString(i)); long ret = SystemProperties.getLong(KEY, -1); assertEquals(i, ret); } }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.bt_debug_feature); TextView tv = (TextView) findViewById(R.id.BTDebugFeaturetxv); tv.setText(Html.fromHtml(getString(R.string.BtDebugFeature))); mChecked = (CheckBox) findViewById(R.id.BTDebugFeatureCb); mChecked.setOnClickListener(this); if (0xFFFFFFFFL == SystemProperties.getLong(KEY_DEBUG_FEATURE, 0)) { mChecked.setChecked(true); } else { mChecked.setChecked(false); } }
private void updateEnableTracesOptions() { long flags = SystemProperties.getLong(Trace.PROPERTY_TRACE_TAG_ENABLEFLAGS, 0); String[] values = mEnableTracesPref.getEntryValues(); int numSet = 0; for (int i = Trace.TRACE_FLAGS_START_BIT; i < values.length; i++) { boolean set = (flags & (1 << i)) != 0; mEnableTracesPref.setValue(i - Trace.TRACE_FLAGS_START_BIT, set); if (set) { numSet++; } } if (numSet == 0) { mEnableTracesPref.setSummary(R.string.enable_traces_summary_none); } else if (numSet == values.length) { mHaveDebugSettings = true; mEnableTracesPref.setSummary(R.string.enable_traces_summary_all); } else { mHaveDebugSettings = true; mEnableTracesPref.setSummary(getString(R.string.enable_traces_summary_num, numSet)); } }
private void logBootEvents(Context ctx) throws IOException { final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); final SharedPreferences prefs = ctx.getSharedPreferences("log_files", Context.MODE_PRIVATE); final String headers = new StringBuilder(512) .append("Build: ") .append(Build.FINGERPRINT) .append("\n") .append("Hardware: ") .append(Build.BOARD) .append("\n") .append("Bootloader: ") .append(Build.BOOTLOADER) .append("\n") .append("Radio: ") .append(Build.RADIO) .append("\n") .append("Kernel: ") .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n")) .append("\n") .toString(); String recovery = RecoverySystem.handleAftermath(); if (recovery != null && db != null) { db.addText("SYSTEM_RECOVERY_LOG", headers + recovery); } if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) { String now = Long.toString(System.currentTimeMillis()); SystemProperties.set("ro.runtime.firstboot", now); if (db != null) db.addText("SYSTEM_BOOT", headers); // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile()) addFileToDropBox(db, prefs, headers, "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG"); addFileToDropBox(db, prefs, headers, "/cache/recovery/log", -LOG_SIZE, "SYSTEM_RECOVERY_LOG"); addFileToDropBox( db, prefs, headers, "/data/dontpanic/apanic_console", -LOG_SIZE, "APANIC_CONSOLE"); addFileToDropBox( db, prefs, headers, "/data/dontpanic/apanic_threads", -LOG_SIZE, "APANIC_THREADS"); } else { if (db != null) db.addText("SYSTEM_RESTART", headers); } // Scan existing tombstones (in case any new ones appeared) File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) { addFileToDropBox( db, prefs, headers, tombstoneFiles[i].getPath(), LOG_SIZE, "SYSTEM_TOMBSTONE"); } // Start watching for new tombstone files; will record them as they occur. // This gets registered with the singleton file observer thread. sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CLOSE_WRITE) { @Override public void onEvent(int event, String path) { try { String filename = new File(TOMBSTONE_DIR, path).getPath(); addFileToDropBox(db, prefs, headers, filename, LOG_SIZE, "SYSTEM_TOMBSTONE"); } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); } } }; sTombstoneObserver.startWatching(); }
/** * Sensor manager implementation that communicates with the built-in system sensors. * * @hide */ public class SystemSensorManager extends SensorManager { private static final int SENSOR_DISABLE = -1; private static final long SENSOR_LOOPMINMS = SystemProperties.getLong( "sensor.loop.minms", 0); // minimal duration of a sensor loop => sleep to prevent notification storm if faster // than that. private static final float MAGNITUDE_THRESHOLD = ((float) SystemProperties.getLong("sensor.magnitude.threshold", 0)) / 1000.0f; private static boolean sSensorModuleInitialized = false; private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>(); /* The thread and the sensor list are global to the process * but the actual thread is spawned on demand */ private static SensorThread sSensorThread; private static int sQueue; // Used within this module from outside SensorManager, don't make private static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>(); static final ArrayList<ListenerDelegate> sListeners = new ArrayList<ListenerDelegate>(); // Common pool of sensor events. static SensorEventPool sPool; // Looper associated with the context in which this instance was created. final Looper mMainLooper; /*-----------------------------------------------------------------------*/ private static class SensorThread { Thread mThread; boolean mSensorsReady; SensorThread() {} @Override protected void finalize() {} // must be called with sListeners lock boolean startLocked() { try { if (mThread == null) { mSensorsReady = false; SensorThreadRunnable runnable = new SensorThreadRunnable(); Thread thread = new Thread(runnable, SensorThread.class.getName()); thread.start(); synchronized (runnable) { while (mSensorsReady == false) { runnable.wait(); } } mThread = thread; } } catch (InterruptedException e) { } return mThread == null ? false : true; } private class SensorThreadRunnable implements Runnable { SensorThreadRunnable() {} private boolean open() { // NOTE: this cannot synchronize on sListeners, since // it's held in the main thread at least until we // return from here. sQueue = sensors_create_queue(); return true; } public void run() { // Log.d(TAG, "entering main sensor thread"); final float[] values = new float[3]; final int[] status = new int[1]; final long timestamp[] = new long[1]; Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); if (!open()) { return; } synchronized (this) { // we've open the driver, we're ready to open the sensors mSensorsReady = true; this.notify(); } while (true) { // wait for an event final int sensor = sensors_data_poll(sQueue, values, status, timestamp); long lastLoopMS = System.currentTimeMillis(); long timeToSleep = SENSOR_LOOPMINMS; int accuracy = status[0]; synchronized (sListeners) { if (sensor == -1 || sListeners.isEmpty()) { // we lost the connection to the event stream. this happens // when the last listener is removed or if there is an error if (sensor == -1 && !sListeners.isEmpty()) { // log a warning in case of abnormal termination Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor); } // we have no more listeners or polling failed, terminate the thread sensors_destroy_queue(sQueue); sQueue = 0; mThread = null; break; } final Sensor sensorObject = sHandleToSensor.get(sensor); if (sensorObject != null) { final float mag = FloatMath.sqrt( values[0] * values[0] + values[1] * values[1] + values[2] * values[2]); if (Math.abs(mag - SensorManager.STANDARD_GRAVITY) > MAGNITUDE_THRESHOLD) { // report the sensor event to all listeners that // care about it. final int size = sListeners.size(); for (int i = 0; i < size; i++) { ListenerDelegate listener = sListeners.get(i); if (listener.hasSensor(sensorObject)) { // this is asynchronous (okay to call // with sListeners lock held). listener.onSensorChangedLocked(sensorObject, values, timestamp, accuracy); } } } } } timeToSleep = SENSOR_LOOPMINMS - (System.currentTimeMillis() - lastLoopMS); lastLoopMS = System.currentTimeMillis(); try { if (timeToSleep > 0) Thread.sleep(timeToSleep); } catch (InterruptedException e) {; } } // Log.d(TAG, "exiting main sensor thread"); } } } /*-----------------------------------------------------------------------*/ private class ListenerDelegate { private final SensorEventListener mSensorEventListener; private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>(); private final Handler mHandler; public SparseBooleanArray mSensors = new SparseBooleanArray(); public SparseBooleanArray mFirstEvent = new SparseBooleanArray(); public SparseIntArray mSensorAccuracies = new SparseIntArray(); ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) { mSensorEventListener = listener; Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; // currently we create one Handler instance per listener, but we could // have one per looper (we'd need to pass the ListenerDelegate // instance to handleMessage and keep track of them separately). mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { final SensorEvent t = (SensorEvent) msg.obj; final int handle = t.sensor.getHandle(); switch (t.sensor.getType()) { // Only report accuracy for sensors that support it. case Sensor.TYPE_MAGNETIC_FIELD: case Sensor.TYPE_ORIENTATION: // call onAccuracyChanged() only if the value changes final int accuracy = mSensorAccuracies.get(handle); if ((t.accuracy >= 0) && (accuracy != t.accuracy)) { mSensorAccuracies.put(handle, t.accuracy); mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy); } break; default: // For other sensors, just report the accuracy once if (mFirstEvent.get(handle) == false) { mFirstEvent.put(handle, true); mSensorEventListener.onAccuracyChanged(t.sensor, SENSOR_STATUS_ACCURACY_HIGH); } break; } mSensorEventListener.onSensorChanged(t); sPool.returnToPool(t); } }; addSensor(sensor); } Object getListener() { return mSensorEventListener; } void addSensor(Sensor sensor) { mSensors.put(sensor.getHandle(), true); mSensorList.add(sensor); } int removeSensor(Sensor sensor) { mSensors.delete(sensor.getHandle()); mSensorList.remove(sensor); return mSensors.size(); } boolean hasSensor(Sensor sensor) { return mSensors.get(sensor.getHandle()); } List<Sensor> getSensors() { return mSensorList; } void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) { SensorEvent t = sPool.getFromPool(); final float[] v = t.values; v[0] = values[0]; v[1] = values[1]; v[2] = values[2]; t.timestamp = timestamp[0]; t.accuracy = accuracy; t.sensor = sensor; Message msg = Message.obtain(); msg.what = 0; msg.obj = t; msg.setAsynchronous(true); mHandler.sendMessage(msg); } } /** {@hide} */ public SystemSensorManager(Looper mainLooper) { mMainLooper = mainLooper; synchronized (sListeners) { if (!sSensorModuleInitialized) { sSensorModuleInitialized = true; nativeClassInit(); // initialize the sensor list sensors_module_init(); final ArrayList<Sensor> fullList = sFullSensorsList; int i = 0; do { Sensor sensor = new Sensor(); i = sensors_module_get_next_sensor(sensor, i); if (i >= 0) { // Log.d(TAG, "found sensor: " + sensor.getName() + // ", handle=" + sensor.getHandle()); fullList.add(sensor); sHandleToSensor.append(sensor.getHandle(), sensor); } } while (i > 0); sPool = new SensorEventPool(sFullSensorsList.size() * 2); sSensorThread = new SensorThread(); } } } /** @hide */ @Override protected List<Sensor> getFullSensorList() { return sFullSensorsList; } private boolean enableSensorLocked(Sensor sensor, int delay) { boolean result = false; for (ListenerDelegate i : sListeners) { if (i.hasSensor(sensor)) { String name = sensor.getName(); int handle = sensor.getHandle(); result = sensors_enable_sensor(sQueue, name, handle, delay); break; } } return result; } private boolean disableSensorLocked(Sensor sensor) { for (ListenerDelegate i : sListeners) { if (i.hasSensor(sensor)) { // not an error, it's just that this sensor is still in use return true; } } String name = sensor.getName(); int handle = sensor.getHandle(); return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE); } /** @hide */ @Override protected boolean registerListenerImpl( SensorEventListener listener, Sensor sensor, int delay, Handler handler) { boolean result = true; synchronized (sListeners) { // look for this listener in our list ListenerDelegate l = null; for (ListenerDelegate i : sListeners) { if (i.getListener() == listener) { l = i; break; } } // if we don't find it, add it to the list if (l == null) { l = new ListenerDelegate(listener, sensor, handler); sListeners.add(l); // if the list is not empty, start our main thread if (!sListeners.isEmpty()) { if (sSensorThread.startLocked()) { if (!enableSensorLocked(sensor, delay)) { // oops. there was an error sListeners.remove(l); result = false; } } else { // there was an error, remove the listener sListeners.remove(l); result = false; } } else { // weird, we couldn't add the listener result = false; } } else if (!l.hasSensor(sensor)) { l.addSensor(sensor); if (!enableSensorLocked(sensor, delay)) { // oops. there was an error l.removeSensor(sensor); result = false; } } } return result; } /** @hide */ @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { synchronized (sListeners) { final int size = sListeners.size(); for (int i = 0; i < size; i++) { ListenerDelegate l = sListeners.get(i); if (l.getListener() == listener) { if (sensor == null) { sListeners.remove(i); // disable all sensors for this listener for (Sensor s : l.getSensors()) { disableSensorLocked(s); } } else if (l.removeSensor(sensor) == 0) { // if we have no more sensors enabled on this listener, // take it off the list. sListeners.remove(i); disableSensorLocked(sensor); } break; } } } } private static native void nativeClassInit(); private static native int sensors_module_init(); private static native int sensors_module_get_next_sensor(Sensor sensor, int next); // Used within this module from outside SensorManager, don't make private static native int sensors_create_queue(); static native void sensors_destroy_queue(int queue); static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable); static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp); }
private void logBootEvents(Context ctx) throws IOException { final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); final SharedPreferences prefs = ctx.getSharedPreferences("log_files", Context.MODE_PRIVATE); final String headers = new StringBuilder(512) .append("Build: ") .append(Build.FINGERPRINT) .append("\n") .append("Hardware: ") .append(Build.BOARD) .append("\n") .append("Revision: ") .append(SystemProperties.get("ro.revision", "")) .append("\n") .append("Bootloader: ") .append(Build.BOOTLOADER) .append("\n") .append("Radio: ") .append(Build.RADIO) .append("\n") .append("Kernel: ") .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n")) .append("\n") .toString(); final String bootReason = SystemProperties.get("ro.boot.bootreason", null); String recovery = RecoverySystem.handleAftermath(); if (recovery != null && db != null) { db.addText("SYSTEM_RECOVERY_LOG", headers + recovery); } String lastKmsgFooter = ""; if (bootReason != null) { lastKmsgFooter = new StringBuilder(512) .append("\n") .append("Boot info:\n") .append("Last boot reason: ") .append(bootReason) .append("\n") .toString(); } if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) { if ("encrypted".equals(SystemProperties.get("ro.crypto.state")) && "trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))) { // Encrypted, first boot to get PIN/pattern/password so data is tmpfs // Don't set ro.runtime.firstboot so that we will do this again // when data is properly mounted } else { String now = Long.toString(System.currentTimeMillis()); SystemProperties.set("ro.runtime.firstboot", now); } if (db != null) db.addText("SYSTEM_BOOT", headers); // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile()) addFileWithFootersToDropBox( db, prefs, headers, lastKmsgFooter, "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG"); addFileWithFootersToDropBox( db, prefs, headers, lastKmsgFooter, "/sys/fs/pstore/console-ramoops", -LOG_SIZE, "SYSTEM_LAST_KMSG"); addFileToDropBox(db, prefs, headers, "/cache/recovery/log", -LOG_SIZE, "SYSTEM_RECOVERY_LOG"); addFileToDropBox( db, prefs, headers, "/cache/recovery/last_kmsg", -LOG_SIZE, "SYSTEM_RECOVERY_KMSG"); addFileToDropBox( db, prefs, headers, "/data/dontpanic/apanic_console", -LOG_SIZE, "APANIC_CONSOLE"); addFileToDropBox( db, prefs, headers, "/data/dontpanic/apanic_threads", -LOG_SIZE, "APANIC_THREADS"); addAuditErrorsToDropBox(db, prefs, headers, -LOG_SIZE, "SYSTEM_AUDIT"); addFsckErrorsToDropBox(db, prefs, headers, -LOG_SIZE, "SYSTEM_FSCK"); } else { if (db != null) db.addText("SYSTEM_RESTART", headers); } // Scan existing tombstones (in case any new ones appeared) File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) { if (tombstoneFiles[i].isFile()) { addFileToDropBox( db, prefs, headers, tombstoneFiles[i].getPath(), LOG_SIZE, "SYSTEM_TOMBSTONE"); } } // Start watching for new tombstone files; will record them as they occur. // This gets registered with the singleton file observer thread. sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CLOSE_WRITE) { @Override public void onEvent(int event, String path) { try { File file = new File(TOMBSTONE_DIR, path); if (file.isFile()) { addFileToDropBox(db, prefs, headers, file.getPath(), LOG_SIZE, "SYSTEM_TOMBSTONE"); } } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); } } }; sTombstoneObserver.startWatching(); }