package com.android.settings.applications; import com.android.settings.R; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.ApplicationErrorReport; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; public class RunningServiceDetails extends Fragment implements RunningState.OnRefreshUiListener { static final String TAG = "RunningServicesDetails"; static final String KEY_UID = "uid"; static final String KEY_PROCESS = "process"; static final String KEY_BACKGROUND = "background"; static final int DIALOG_CONFIRM_STOP = 1; ActivityManager mAm; LayoutInflater mInflater; RunningState mState; boolean mHaveData; int mUid; String mProcessName; boolean mShowBackground; RunningState.MergedItem mMergedItem; View mRootView; ViewGroup mAllDetails; ViewGroup mSnippet; RunningProcessesView.ActiveItem mSnippetActiveItem; RunningProcessesView.ViewHolder mSnippetViewHolder; int mNumServices, mNumProcesses; TextView mServicesHeader; TextView mProcessesHeader; final ArrayList mActiveDetails = new ArrayList(); class ActiveDetail implements View.OnClickListener { View mRootView; Button mStopButton; Button mReportButton; RunningState.ServiceItem mServiceItem; RunningProcessesView.ActiveItem mActiveItem; RunningProcessesView.ViewHolder mViewHolder; PendingIntent mManageIntent; ComponentName mInstaller; void stopActiveService(boolean confirmed) { RunningState.ServiceItem si = mServiceItem; if (!confirmed) { if ((si.mServiceInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { showConfirmStopDialog(si.mRunningService.service); return; } } getActivity().stopService(new Intent().setComponent(si.mRunningService.service)); if (mMergedItem == null) { // If this is gone, we are gone. mState.updateNow(); finish(); } else if (!mShowBackground && mMergedItem.mServices.size() <= 1) { // If there was only one service, we are finishing it, // so no reason for the UI to stick around. mState.updateNow(); finish(); } else { mState.updateNow(); } } public void onClick(View v) { if (v == mReportButton) { ApplicationErrorReport report = new ApplicationErrorReport(); report.type = ApplicationErrorReport.TYPE_RUNNING_SERVICE; report.packageName = mServiceItem.mServiceInfo.packageName; report.installerPackageName = mInstaller.getPackageName(); report.processName = mServiceItem.mRunningService.process; report.time = System.currentTimeMillis(); report.systemApp = (mServiceItem.mServiceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; ApplicationErrorReport.RunningServiceInfo info = new ApplicationErrorReport.RunningServiceInfo(); if (mActiveItem.mFirstRunTime >= 0) { info.durationMillis = SystemClock.elapsedRealtime()-mActiveItem.mFirstRunTime; } else { info.durationMillis = -1; } ComponentName comp = new ComponentName(mServiceItem.mServiceInfo.packageName, mServiceItem.mServiceInfo.name); File filename = getActivity().getFileStreamPath("service_dump.txt"); FileOutputStream output = null; try { output = new FileOutputStream(filename); Debug.dumpService("activity", output.getFD(), new String[] { "-a", "service", comp.flattenToString() }); } catch (IOException e) { Log.w(TAG, "Can't dump service: " + comp, e); } finally { if (output != null) try { output.close(); } catch (IOException e) {} } FileInputStream input = null; try { input = new FileInputStream(filename); byte[] buffer = new byte[(int) filename.length()]; input.read(buffer); info.serviceDetails = new String(buffer); } catch (IOException e) { Log.w(TAG, "Can't read service dump: " + comp, e); } finally { if (input != null) try { input.close(); } catch (IOException e) {} } filename.delete(); Log.i(TAG, "Details: " + info.serviceDetails); report.runningServiceInfo = info; Intent result = new Intent(Intent.ACTION_APP_ERROR); result.setComponent(mInstaller); result.putExtra(Intent.EXTRA_BUG_REPORT, report); result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(result); return; } if (mManageIntent != null) { try { getActivity().startIntentSender(mManageIntent.getIntentSender(), null, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, 0); } catch (IntentSender.SendIntentException e) { Log.w(TAG, e); } catch (IllegalArgumentException e) { Log.w(TAG, e); } catch (ActivityNotFoundException e) { Log.w(TAG, e); } } else if (mServiceItem != null) { stopActiveService(false); } else if (mActiveItem.mItem.mBackground) { // Background process. Just kill it. mAm.killBackgroundProcesses(mActiveItem.mItem.mPackageInfo.packageName); finish(); } else { // Heavy-weight process. We'll do a force-stop on it. mAm.forceStopPackage(mActiveItem.mItem.mPackageInfo.packageName); finish(); } } } StringBuilder mBuilder = new StringBuilder(128); boolean findMergedItem() { RunningState.MergedItem item = null; ArrayList newItems = mShowBackground ? mState.getCurrentBackgroundItems() : mState.getCurrentMergedItems(); if (newItems != null) { for (int i=0; i