/* * Copyright (C) 2015. Jared Rummler <jared.rummler@gmail.com> * * 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.jaredrummler.android.processes.sample.dialogs; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; import android.os.SystemClock; import android.text.Spanned; import android.text.format.Formatter; import android.util.Log; import com.jaredrummler.android.processes.models.AndroidAppProcess; import com.jaredrummler.android.processes.models.Stat; import com.jaredrummler.android.processes.models.Statm; import com.jaredrummler.android.processes.models.Status; import com.jaredrummler.android.processes.sample.utils.HtmlBuilder; import com.jaredrummler.android.processes.sample.utils.Utils; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Locale; public class ProcessInfoDialog extends DialogFragment { private static final String TAG = "ProcessInfoDialog"; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AndroidAppProcess process = getArguments().getParcelable("process"); return new AlertDialog.Builder(getActivity()) .setTitle(Utils.getName(getActivity(), process)) .setMessage(getProcessInfo(process)) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create(); } private Spanned getProcessInfo(AndroidAppProcess process) { HtmlBuilder html = new HtmlBuilder(); html.p().strong("NAME: ").append(process.name).close(); html.p().strong("POLICY: ").append(process.foreground ? "fg" : "bg").close(); html.p().strong("PID: ").append(process.pid).close(); try { Status status = process.status(); html.p().strong("UID/GID: ").append(status.getUid()).append('/').append(status.getGid()).close(); } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/status.", process.pid)); } // should probably be run in a background thread. try { Stat stat = process.stat(); html.p().strong("PPID: ").append(stat.ppid()).close(); long bootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime(); long startTime = bootTime + (10 * stat.starttime()); SimpleDateFormat sdf = new SimpleDateFormat("MMM d, yyyy KK:mm:ss a", Locale.getDefault()); html.p().strong("START TIME: ").append(sdf.format(startTime)).close(); html.p().strong("CPU TIME: ").append((stat.stime() + stat.utime()) / 100).close(); html.p().strong("NICE: ").append(stat.nice()).close(); int rtPriority = stat.rt_priority(); if (rtPriority == 0) { html.p().strong("SCHEDULING PRIORITY: ").append("non-real-time").close(); } else if (rtPriority >= 1 && rtPriority <= 99) { html.p().strong("SCHEDULING PRIORITY: ").append("real-time").close(); } long userModeTicks = stat.utime(); long kernelModeTicks = stat.stime(); long percentOfTimeUserMode; long percentOfTimeKernelMode; if ((kernelModeTicks + userModeTicks) > 0) { percentOfTimeUserMode = (userModeTicks * 100) / (userModeTicks + kernelModeTicks); percentOfTimeKernelMode = (kernelModeTicks * 100) / (userModeTicks + kernelModeTicks); html.p().strong("TIME EXECUTED IN USER MODE: ").append(percentOfTimeUserMode + "%").close(); html.p().strong("TIME EXECUTED IN KERNEL MODE: ").append(percentOfTimeKernelMode + "%").close(); } } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/stat.", process.pid)); } try { Statm statm = process.statm(); html.p().strong("SIZE: ").append(Formatter.formatFileSize(getActivity(), statm.getSize())).close(); html.p().strong("RSS: ").append(Formatter.formatFileSize(getActivity(), statm.getResidentSetSize())).close(); } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/statm.", process.pid)); } try { html.p().strong("OOM SCORE: ").append(process.oom_score()).close(); } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/oom_score.", process.pid)); } try { html.p().strong("OOM ADJ: ").append(process.oom_adj()).close(); } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/oom_adj.", process.pid)); } try { html.p().strong("OOM SCORE ADJ: ").append(process.oom_score_adj()).close(); } catch (IOException e) { Log.d(TAG, String.format("Error reading /proc/%d/oom_score_adj.", process.pid)); } return html.toSpan(); } }