1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.traceur; 18 19 import com.google.android.collect.Sets; 20 21 import android.app.IntentService; 22 import android.app.Notification; 23 import android.app.NotificationManager; 24 import android.app.PendingIntent; 25 import android.app.Service; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.preference.PreferenceManager; 29 30 import java.io.File; 31 32 public class AtraceService extends IntentService { 33 34 private static String INTENT_ACTION_START_TRACING = "com.android.traceur.START_TRACING"; 35 private static String INTENT_ACTION_STOP_TRACING = "com.android.traceur.STOP_TRACING"; 36 37 private static String INTENT_EXTRA_FILENAME = "filename"; 38 private static String INTENT_EXTRA_TAGS= "tags"; 39 private static String INTENT_EXTRA_BUFFER = "buffer"; 40 private static String INTENT_EXTRA_APPS = "apps"; 41 42 private static int TRACE_NOTIFICATION = 1; 43 private static int SAVING_TRACE_NOTIFICATION = 2; 44 45 public static void startTracing(final Context context, 46 String tags, int bufferSizeKb, boolean apps) { 47 Intent intent = new Intent(context, AtraceService.class); 48 intent.setAction(INTENT_ACTION_START_TRACING); 49 intent.putExtra(INTENT_EXTRA_TAGS, tags); 50 intent.putExtra(INTENT_EXTRA_BUFFER, bufferSizeKb); 51 intent.putExtra(INTENT_EXTRA_APPS, apps); 52 context.startService(intent); 53 } 54 55 public static void stopTracing(final Context context) { 56 Intent intent = new Intent(context, AtraceService.class); 57 intent.setAction(INTENT_ACTION_STOP_TRACING); 58 intent.putExtra(INTENT_EXTRA_FILENAME, AtraceUtils.getOutputFilename()); 59 context.startService(intent); 60 } 61 62 public AtraceService() { 63 super("AtraceService"); 64 setIntentRedelivery(true); 65 } 66 67 @Override 68 public void onHandleIntent(Intent intent) { 69 if (intent.getAction().equals(INTENT_ACTION_START_TRACING)) { 70 startTracingInternal(intent.getStringExtra(INTENT_EXTRA_TAGS), 71 intent.getIntExtra(INTENT_EXTRA_BUFFER, 72 Integer.parseInt(getApplicationContext() 73 .getString(R.string.default_buffer_size))), 74 intent.getBooleanExtra(INTENT_EXTRA_APPS, false)); 75 } else if (intent.getAction().equals(INTENT_ACTION_STOP_TRACING)) { 76 stopTracingInternal(intent.getStringExtra(INTENT_EXTRA_FILENAME)); 77 } 78 } 79 80 private void startTracingInternal(String tags, int bufferSizeKb, boolean appTracing) { 81 Context context = getApplicationContext(); 82 Intent stopIntent = new Intent(Receiver.STOP_ACTION, 83 null, context, Receiver.class); 84 85 String title = context.getString(R.string.trace_is_being_recorded); 86 String msg = context.getString(R.string.tap_to_stop_tracing); 87 88 Notification notification = 89 new Notification.Builder(context, Receiver.NOTIFICATION_CHANNEL) 90 .setSmallIcon(R.drawable.stat_sys_adb) 91 .setContentTitle(title) 92 .setTicker(title) 93 .setContentText(msg) 94 .setContentIntent( 95 PendingIntent.getBroadcast(context, 0, stopIntent, 0)) 96 .setOngoing(true) 97 .setLocalOnly(true) 98 .setColor(getColor( 99 com.android.internal.R.color.system_notification_accent_color)) 100 .build(); 101 102 startForeground(TRACE_NOTIFICATION, notification); 103 104 if (AtraceUtils.atraceStart(tags, bufferSizeKb, appTracing)) { 105 stopForeground(Service.STOP_FOREGROUND_DETACH); 106 } else { 107 // Starting the trace was unsuccessful, so ensure that tracing 108 // is stopped and the preference is reset. 109 AtraceUtils.atraceStop(); 110 PreferenceManager.getDefaultSharedPreferences(context) 111 .edit().putBoolean(context.getString(R.string.pref_key_tracing_on), 112 false).apply(); 113 QsService.updateTile(); 114 stopForeground(Service.STOP_FOREGROUND_REMOVE); 115 } 116 } 117 118 private void stopTracingInternal(String outputFilename) { 119 NotificationManager notificationManager = 120 getSystemService(NotificationManager.class); 121 122 Notification notification = 123 new Notification.Builder(this, Receiver.NOTIFICATION_CHANNEL) 124 .setSmallIcon(R.drawable.stat_sys_adb) 125 .setContentTitle(getString(R.string.saving_trace)) 126 .setTicker(getString(R.string.saving_trace)) 127 .setLocalOnly(true) 128 .setProgress(1, 0, true) 129 .setColor(getColor( 130 com.android.internal.R.color.system_notification_accent_color)) 131 .build(); 132 133 startForeground(SAVING_TRACE_NOTIFICATION, notification); 134 135 notificationManager.cancel(TRACE_NOTIFICATION); 136 137 File file = AtraceUtils.getOutputFile(outputFilename); 138 139 if (AtraceUtils.atraceDump(file)) { 140 FileSender.postNotification(getApplicationContext(), file); 141 } 142 143 stopForeground(Service.STOP_FOREGROUND_REMOVE); 144 } 145 } 146