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