1bde75706592c77379fb6546283e733abaca6fe04Sen Hu/* 2bde75706592c77379fb6546283e733abaca6fe04Sen Hu * Copyright (C) 2010 The Android Open Source Project 3bde75706592c77379fb6546283e733abaca6fe04Sen Hu * 4bde75706592c77379fb6546283e733abaca6fe04Sen Hu * Licensed under the Apache License, Version 2.0 (the "License"); 5bde75706592c77379fb6546283e733abaca6fe04Sen Hu * you may not use this file except in compliance with the License. 6bde75706592c77379fb6546283e733abaca6fe04Sen Hu * You may obtain a copy of the License at 7bde75706592c77379fb6546283e733abaca6fe04Sen Hu * 8bde75706592c77379fb6546283e733abaca6fe04Sen Hu * http://www.apache.org/licenses/LICENSE-2.0 9bde75706592c77379fb6546283e733abaca6fe04Sen Hu * 10bde75706592c77379fb6546283e733abaca6fe04Sen Hu * Unless required by applicable law or agreed to in writing, software 11bde75706592c77379fb6546283e733abaca6fe04Sen Hu * distributed under the License is distributed on an "AS IS" BASIS, 12bde75706592c77379fb6546283e733abaca6fe04Sen Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bde75706592c77379fb6546283e733abaca6fe04Sen Hu * See the License for the specific language governing permissions and 14bde75706592c77379fb6546283e733abaca6fe04Sen Hu * limitations under the License. 15bde75706592c77379fb6546283e733abaca6fe04Sen Hu */ 16bde75706592c77379fb6546283e733abaca6fe04Sen Hu 17bde75706592c77379fb6546283e733abaca6fe04Sen Hupackage com.android.server; 18bde75706592c77379fb6546283e733abaca6fe04Sen Hu 19bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.content.ContentResolver; 20bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.os.DropBoxManager; 21bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.os.FileObserver; 22bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.os.Binder; 23bde75706592c77379fb6546283e733abaca6fe04Sen Hu 24bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.util.Slog; 25bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.content.Context; 26bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.database.ContentObserver; 27bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.os.SystemProperties; 28bde75706592c77379fb6546283e733abaca6fe04Sen Huimport android.provider.Settings; 29bde75706592c77379fb6546283e733abaca6fe04Sen Huimport com.android.internal.os.SamplingProfilerIntegration; 30bde75706592c77379fb6546283e733abaca6fe04Sen Hu 31bde75706592c77379fb6546283e733abaca6fe04Sen Huimport java.io.File; 32bde75706592c77379fb6546283e733abaca6fe04Sen Huimport java.io.FileDescriptor; 33bde75706592c77379fb6546283e733abaca6fe04Sen Huimport java.io.IOException; 34bde75706592c77379fb6546283e733abaca6fe04Sen Huimport java.io.PrintWriter; 35bde75706592c77379fb6546283e733abaca6fe04Sen Hu 36bde75706592c77379fb6546283e733abaca6fe04Sen Hupublic class SamplingProfilerService extends Binder { 37bde75706592c77379fb6546283e733abaca6fe04Sen Hu 38bde75706592c77379fb6546283e733abaca6fe04Sen Hu private static final String TAG = "SamplingProfilerService"; 39bde75706592c77379fb6546283e733abaca6fe04Sen Hu private static final boolean LOCAL_LOGV = false; 40bde75706592c77379fb6546283e733abaca6fe04Sen Hu public static final String SNAPSHOT_DIR = SamplingProfilerIntegration.SNAPSHOT_DIR; 41bde75706592c77379fb6546283e733abaca6fe04Sen Hu 42eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey private final Context mContext; 43bde75706592c77379fb6546283e733abaca6fe04Sen Hu private FileObserver snapshotObserver; 44bde75706592c77379fb6546283e733abaca6fe04Sen Hu 45bde75706592c77379fb6546283e733abaca6fe04Sen Hu public SamplingProfilerService(Context context) { 46eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext = context; 47bde75706592c77379fb6546283e733abaca6fe04Sen Hu registerSettingObserver(context); 48bde75706592c77379fb6546283e733abaca6fe04Sen Hu startWorking(context); 49bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 50bde75706592c77379fb6546283e733abaca6fe04Sen Hu 51bde75706592c77379fb6546283e733abaca6fe04Sen Hu private void startWorking(Context context) { 52bde75706592c77379fb6546283e733abaca6fe04Sen Hu if (LOCAL_LOGV) Slog.v(TAG, "starting SamplingProfilerService!"); 53bde75706592c77379fb6546283e733abaca6fe04Sen Hu 54bde75706592c77379fb6546283e733abaca6fe04Sen Hu final DropBoxManager dropbox = 55bde75706592c77379fb6546283e733abaca6fe04Sen Hu (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE); 56bde75706592c77379fb6546283e733abaca6fe04Sen Hu 57bde75706592c77379fb6546283e733abaca6fe04Sen Hu // before FileObserver is ready, there could have already been some snapshots 58bde75706592c77379fb6546283e733abaca6fe04Sen Hu // in the directory, we don't want to miss them 59bde75706592c77379fb6546283e733abaca6fe04Sen Hu File[] snapshotFiles = new File(SNAPSHOT_DIR).listFiles(); 60bde75706592c77379fb6546283e733abaca6fe04Sen Hu for (int i = 0; snapshotFiles != null && i < snapshotFiles.length; i++) { 61bde75706592c77379fb6546283e733abaca6fe04Sen Hu handleSnapshotFile(snapshotFiles[i], dropbox); 62bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 63bde75706592c77379fb6546283e733abaca6fe04Sen Hu 64bde75706592c77379fb6546283e733abaca6fe04Sen Hu // detect new snapshot and put it in dropbox 65bde75706592c77379fb6546283e733abaca6fe04Sen Hu // delete it afterwards no matter what happened before 66bde75706592c77379fb6546283e733abaca6fe04Sen Hu // Note: needs listening at event ATTRIB rather than CLOSE_WRITE, because we set the 67bde75706592c77379fb6546283e733abaca6fe04Sen Hu // readability of snapshot files after writing them! 68bde75706592c77379fb6546283e733abaca6fe04Sen Hu snapshotObserver = new FileObserver(SNAPSHOT_DIR, FileObserver.ATTRIB) { 69bde75706592c77379fb6546283e733abaca6fe04Sen Hu @Override 70bde75706592c77379fb6546283e733abaca6fe04Sen Hu public void onEvent(int event, String path) { 71bde75706592c77379fb6546283e733abaca6fe04Sen Hu handleSnapshotFile(new File(SNAPSHOT_DIR, path), dropbox); 72bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 73bde75706592c77379fb6546283e733abaca6fe04Sen Hu }; 74bde75706592c77379fb6546283e733abaca6fe04Sen Hu snapshotObserver.startWatching(); 75bde75706592c77379fb6546283e733abaca6fe04Sen Hu 76bde75706592c77379fb6546283e733abaca6fe04Sen Hu if (LOCAL_LOGV) Slog.v(TAG, "SamplingProfilerService activated"); 77bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 78bde75706592c77379fb6546283e733abaca6fe04Sen Hu 79bde75706592c77379fb6546283e733abaca6fe04Sen Hu private void handleSnapshotFile(File file, DropBoxManager dropbox) { 80bde75706592c77379fb6546283e733abaca6fe04Sen Hu try { 81bde75706592c77379fb6546283e733abaca6fe04Sen Hu dropbox.addFile(TAG, file, 0); 82bde75706592c77379fb6546283e733abaca6fe04Sen Hu if (LOCAL_LOGV) Slog.v(TAG, file.getPath() + " added to dropbox"); 83bde75706592c77379fb6546283e733abaca6fe04Sen Hu } catch (IOException e) { 84bde75706592c77379fb6546283e733abaca6fe04Sen Hu Slog.e(TAG, "Can't add " + file.getPath() + " to dropbox", e); 85bde75706592c77379fb6546283e733abaca6fe04Sen Hu } finally { 86bde75706592c77379fb6546283e733abaca6fe04Sen Hu file.delete(); 87bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 88bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 89bde75706592c77379fb6546283e733abaca6fe04Sen Hu 90bde75706592c77379fb6546283e733abaca6fe04Sen Hu private void registerSettingObserver(Context context) { 91bde75706592c77379fb6546283e733abaca6fe04Sen Hu ContentResolver contentResolver = context.getContentResolver(); 92bde75706592c77379fb6546283e733abaca6fe04Sen Hu contentResolver.registerContentObserver( 93bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.getUriFor(Settings.Global.SAMPLING_PROFILER_MS), 94bde75706592c77379fb6546283e733abaca6fe04Sen Hu false, new SamplingProfilerSettingsObserver(contentResolver)); 95bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 96bde75706592c77379fb6546283e733abaca6fe04Sen Hu 97bde75706592c77379fb6546283e733abaca6fe04Sen Hu @Override 98bde75706592c77379fb6546283e733abaca6fe04Sen Hu protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 99eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 100eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 101bde75706592c77379fb6546283e733abaca6fe04Sen Hu pw.println("SamplingProfilerService:"); 102bde75706592c77379fb6546283e733abaca6fe04Sen Hu pw.println("Watching directory: " + SNAPSHOT_DIR); 103bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 104bde75706592c77379fb6546283e733abaca6fe04Sen Hu 105bde75706592c77379fb6546283e733abaca6fe04Sen Hu private class SamplingProfilerSettingsObserver extends ContentObserver { 106bde75706592c77379fb6546283e733abaca6fe04Sen Hu private ContentResolver mContentResolver; 107bde75706592c77379fb6546283e733abaca6fe04Sen Hu public SamplingProfilerSettingsObserver(ContentResolver contentResolver) { 108bde75706592c77379fb6546283e733abaca6fe04Sen Hu super(null); 109bde75706592c77379fb6546283e733abaca6fe04Sen Hu mContentResolver = contentResolver; 110bde75706592c77379fb6546283e733abaca6fe04Sen Hu onChange(false); 111bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 112bde75706592c77379fb6546283e733abaca6fe04Sen Hu @Override 113bde75706592c77379fb6546283e733abaca6fe04Sen Hu public void onChange(boolean selfChange) { 114bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Integer samplingProfilerMs = Settings.Global.getInt( 115bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown mContentResolver, Settings.Global.SAMPLING_PROFILER_MS, 0); 116bde75706592c77379fb6546283e733abaca6fe04Sen Hu // setting this secure property will start or stop sampling profiler, 117d7ad0d28372bba03a3b6c5d01e0e7b0066e51374Brad Fitzpatrick // as well as adjust the the time between taking snapshots. 118d7ad0d28372bba03a3b6c5d01e0e7b0066e51374Brad Fitzpatrick SystemProperties.set("persist.sys.profiler_ms", samplingProfilerMs.toString()); 119bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 120bde75706592c77379fb6546283e733abaca6fe04Sen Hu } 121bde75706592c77379fb6546283e733abaca6fe04Sen Hu} 122