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