FileSender.java revision 18f1b43e4bb740e7832acc614e83cc334c671d03
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 17package com.android.traceur; 18 19import android.accounts.Account; 20import android.accounts.AccountManager; 21import android.app.Notification; 22import android.app.NotificationManager; 23import android.app.PendingIntent; 24import android.content.Context; 25import android.support.v4.content.FileProvider; 26import android.content.Intent; 27import android.net.Uri; 28import android.os.SystemProperties; 29import android.util.Patterns; 30 31import java.io.File; 32 33/** 34 * Sends bugreport-y files, adapted from fw/base/packages/Shell's BugreportReceiver. 35 */ 36public class FileSender { 37 38 private static final String AUTHORITY = "com.android.traceur.files"; 39 40 public static void postCaptureNotification(Context context, File file) { 41 final Notification.Builder builder = new Notification.Builder(context) 42 .setSmallIcon(R.drawable.stat_sys_adb) 43 .setContentTitle("Dumping systrace") 44 .setTicker("Dumping systrace") 45 .setLocalOnly(true) 46 .setDefaults(Notification.DEFAULT_VIBRATE) 47 .setProgress(1, 0, true) 48 .setColor(context.getColor( 49 com.android.internal.R.color.system_notification_accent_color)); 50 51 NotificationManager.from(context).notify(file.getName(), 0, builder.build()); 52 } 53 54 public static void postNotification(Context context, File file) { 55 // Files are kept on private storage, so turn into Uris that we can 56 // grant temporary permissions for. 57 final Uri traceUri = getUriForFile(context, file); 58 59 Intent sendIntent = buildSendIntent(context, traceUri); 60 sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 61 62 final Notification.Builder builder = new Notification.Builder(context) 63 .setSmallIcon(R.drawable.stat_sys_adb) 64 .setContentTitle("Systrace captured") 65 .setTicker("Systrace captured") 66 .setContentText("Touch to share your systrace") 67 .setContentIntent(PendingIntent.getActivity( 68 context, traceUri.hashCode(), sendIntent, PendingIntent.FLAG_ONE_SHOT 69 | PendingIntent.FLAG_CANCEL_CURRENT)) 70 .setAutoCancel(true) 71 .setLocalOnly(true) 72 .setDefaults(Notification.DEFAULT_VIBRATE) 73 .setColor(context.getColor( 74 com.android.internal.R.color.system_notification_accent_color)); 75 76 NotificationManager.from(context).notify(file.getName(), 0, builder.build()); 77 } 78 79 public static void send(Context context, File file) { 80 // Files are kept on private storage, so turn into Uris that we can 81 // grant temporary permissions for. 82 final Uri traceUri = getUriForFile(context, file); 83 84 Intent sendIntent = buildSendIntent(context, traceUri); 85 sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 86 87 context.startActivity(sendIntent); 88 } 89 90 private static Uri getUriForFile(Context context, File file) { 91 return FileProvider.getUriForFile(context, AUTHORITY, file); 92 } 93 94 /** 95 * Build {@link Intent} that can be used to share the given bugreport. 96 */ 97 private static Intent buildSendIntent(Context context, Uri traceUri) { 98 final Intent intent = new Intent(Intent.ACTION_SEND); 99 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 100 intent.addCategory(Intent.CATEGORY_DEFAULT); 101 intent.setType("application/vnd.android.systrace"); 102 103 intent.putExtra(Intent.EXTRA_SUBJECT, traceUri.getLastPathSegment()); 104 intent.putExtra(Intent.EXTRA_TEXT, SystemProperties.get("ro.build.description")); 105 intent.putExtra(Intent.EXTRA_STREAM, traceUri); 106 107 final Account sendToAccount = findSendToAccount(context); 108 if (sendToAccount != null) { 109 intent.putExtra(Intent.EXTRA_EMAIL, new String[] { sendToAccount.name }); 110 } 111 112 return intent; 113 } 114 115 /** 116 * Find the best matching {@link Account} based on build properties. 117 */ 118 private static Account findSendToAccount(Context context) { 119 final AccountManager am = (AccountManager) context.getSystemService( 120 Context.ACCOUNT_SERVICE); 121 122 String preferredDomain = SystemProperties.get("sendbug.preferred.domain"); 123 if (!preferredDomain.startsWith("@")) { 124 preferredDomain = "@" + preferredDomain; 125 } 126 127 final Account[] accounts = am.getAccounts(); 128 Account foundAccount = null; 129 for (Account account : accounts) { 130 if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { 131 if (!preferredDomain.isEmpty()) { 132 // if we have a preferred domain and it matches, return; otherwise keep 133 // looking 134 if (account.name.endsWith(preferredDomain)) { 135 return account; 136 } else { 137 foundAccount = account; 138 } 139 // if we don't have a preferred domain, just return since it looks like 140 // an email address 141 } else { 142 return account; 143 } 144 } 145 } 146 return foundAccount; 147 } 148} 149