• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.accounts.Account;
20 import android.accounts.AccountManager;
21 import android.content.ClipData;
22 import android.content.ClipDescription;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.Uri;
26 import android.os.Build;
27 import android.os.SystemProperties;
28 import android.util.Log;
29 import android.util.Patterns;
30 
31 import androidx.core.content.FileProvider;
32 
33 import java.io.File;
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * Sends bugreport-y files, adapted from fw/base/packages/Shell's BugreportReceiver.
39  */
40 public class FileSender {
41     private static final String TAG = "Traceur";
42     private static final String MIME_TYPE = "application/vnd.android.systrace";
43 
getUriForFiles(Context context, List<File> files, String authority)44     public static List<Uri> getUriForFiles(Context context, List<File> files, String authority) {
45         List<Uri> uris = new ArrayList();
46         for (File file : files) {
47             uris.add(FileProvider.getUriForFile(context, authority, file));
48         }
49         return uris;
50     }
51 
52     /**
53      * Build {@link Intent} that can be used to share the given bugreport.
54      */
buildSendIntent(Context context, List<Uri> traceUris)55     public static Intent buildSendIntent(Context context, List<Uri> traceUris) {
56         final CharSequence description = Build.FINGERPRINT;
57 
58         final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
59         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
60         intent.addCategory(Intent.CATEGORY_DEFAULT);
61         intent.setType(MIME_TYPE);
62 
63         if (!traceUris.isEmpty()) {
64             intent.putExtra(Intent.EXTRA_SUBJECT, traceUris.get(0).getLastPathSegment());
65             intent.putExtra(Intent.EXTRA_STREAM, new ArrayList(traceUris));
66 
67             // Explicitly set the clip data; see b/119399115
68             intent.setClipData(buildClipData(traceUris));
69         } else {
70             Log.e(TAG, "There are no URIs to attach to this send intent. " +
71                     "An error may have occurred while tracing or retrieving trace files.");
72         }
73         intent.putExtra(Intent.EXTRA_TEXT, description);
74 
75         final Account sendToAccount = findSendToAccount(context);
76         if (sendToAccount != null) {
77             intent.putExtra(Intent.EXTRA_EMAIL, new String[] { sendToAccount.name });
78         }
79 
80         return intent;
81     }
82 
buildClipData(List<Uri> uris)83     private static ClipData buildClipData(List<Uri> uris) {
84         ArrayList<ClipData.Item> items = new ArrayList();
85         for (Uri uri : uris) {
86             items.add(new ClipData.Item(Build.FINGERPRINT, null, uri));
87         }
88         ClipDescription description = new ClipDescription(null, new String[] { MIME_TYPE });
89         return new ClipData(description, items);
90     }
91 
92 
93     /**
94      * Find the best matching {@link Account} based on build properties.
95      */
findSendToAccount(Context context)96     private static Account findSendToAccount(Context context) {
97         final AccountManager am = (AccountManager) context.getSystemService(
98                 Context.ACCOUNT_SERVICE);
99 
100         String preferredDomain = SystemProperties.get("sendbug.preferred.domain");
101         if (!preferredDomain.startsWith("@")) {
102             preferredDomain = "@" + preferredDomain;
103         }
104 
105         final Account[] accounts = am.getAccounts();
106         Account foundAccount = null;
107         for (Account account : accounts) {
108             if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
109                 if (!preferredDomain.isEmpty()) {
110                     // if we have a preferred domain and it matches, return; otherwise keep
111                     // looking
112                     if (account.name.endsWith(preferredDomain)) {
113                         return account;
114                     } else {
115                         foundAccount = account;
116                     }
117                     // if we don't have a preferred domain, just return since it looks like
118                     // an email address
119                 } else {
120                     return account;
121                 }
122             }
123         }
124         return foundAccount;
125     }
126 }
127