| /* | |
| * Copyright (C) 2010 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package com.android.server; | |
| import android.content.ContentResolver; | |
| import android.os.DropBoxManager; | |
| import android.os.FileObserver; | |
| import android.os.Binder; | |
| import android.util.Slog; | |
| import android.content.Context; | |
| import android.database.ContentObserver; | |
| import android.os.SystemProperties; | |
| import android.provider.Settings; | |
| import com.android.internal.os.SamplingProfilerIntegration; | |
| import java.io.File; | |
| import java.io.FileDescriptor; | |
| import java.io.IOException; | |
| import java.io.PrintWriter; | |
| public class SamplingProfilerService extends Binder { | |
| private static final String TAG = "SamplingProfilerService"; | |
| private static final boolean LOCAL_LOGV = false; | |
| public static final String SNAPSHOT_DIR = SamplingProfilerIntegration.SNAPSHOT_DIR; | |
| private final Context mContext; | |
| private FileObserver snapshotObserver; | |
| public SamplingProfilerService(Context context) { | |
| mContext = context; | |
| registerSettingObserver(context); | |
| startWorking(context); | |
| } | |
| private void startWorking(Context context) { | |
| if (LOCAL_LOGV) Slog.v(TAG, "starting SamplingProfilerService!"); | |
| final DropBoxManager dropbox = | |
| (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE); | |
| // before FileObserver is ready, there could have already been some snapshots | |
| // in the directory, we don't want to miss them | |
| File[] snapshotFiles = new File(SNAPSHOT_DIR).listFiles(); | |
| for (int i = 0; snapshotFiles != null && i < snapshotFiles.length; i++) { | |
| handleSnapshotFile(snapshotFiles[i], dropbox); | |
| } | |
| // detect new snapshot and put it in dropbox | |
| // delete it afterwards no matter what happened before | |
| // Note: needs listening at event ATTRIB rather than CLOSE_WRITE, because we set the | |
| // readability of snapshot files after writing them! | |
| snapshotObserver = new FileObserver(SNAPSHOT_DIR, FileObserver.ATTRIB) { | |
| @Override | |
| public void onEvent(int event, String path) { | |
| handleSnapshotFile(new File(SNAPSHOT_DIR, path), dropbox); | |
| } | |
| }; | |
| snapshotObserver.startWatching(); | |
| if (LOCAL_LOGV) Slog.v(TAG, "SamplingProfilerService activated"); | |
| } | |
| private void handleSnapshotFile(File file, DropBoxManager dropbox) { | |
| try { | |
| dropbox.addFile(TAG, file, 0); | |
| if (LOCAL_LOGV) Slog.v(TAG, file.getPath() + " added to dropbox"); | |
| } catch (IOException e) { | |
| Slog.e(TAG, "Can't add " + file.getPath() + " to dropbox", e); | |
| } finally { | |
| file.delete(); | |
| } | |
| } | |
| private void registerSettingObserver(Context context) { | |
| ContentResolver contentResolver = context.getContentResolver(); | |
| contentResolver.registerContentObserver( | |
| Settings.Global.getUriFor(Settings.Global.SAMPLING_PROFILER_MS), | |
| false, new SamplingProfilerSettingsObserver(contentResolver)); | |
| } | |
| @Override | |
| protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { | |
| mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); | |
| pw.println("SamplingProfilerService:"); | |
| pw.println("Watching directory: " + SNAPSHOT_DIR); | |
| } | |
| private class SamplingProfilerSettingsObserver extends ContentObserver { | |
| private ContentResolver mContentResolver; | |
| public SamplingProfilerSettingsObserver(ContentResolver contentResolver) { | |
| super(null); | |
| mContentResolver = contentResolver; | |
| onChange(false); | |
| } | |
| @Override | |
| public void onChange(boolean selfChange) { | |
| Integer samplingProfilerMs = Settings.Global.getInt( | |
| mContentResolver, Settings.Global.SAMPLING_PROFILER_MS, 0); | |
| // setting this secure property will start or stop sampling profiler, | |
| // as well as adjust the the time between taking snapshots. | |
| SystemProperties.set("persist.sys.profiler_ms", samplingProfilerMs.toString()); | |
| } | |
| } | |
| } |