• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 package com.android.commands.sendbug;
17 
18 import android.accounts.Account;
19 import android.accounts.IAccountManager;
20 import android.app.ActivityManagerNative;
21 import android.app.IActivityManager;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.IPackageManager;
25 import android.content.pm.ResolveInfo;
26 import android.net.Uri;
27 import android.os.RemoteException;
28 import android.os.ServiceManager;
29 import android.os.SystemProperties;
30 import android.os.UserHandle;
31 import android.util.Log;
32 
33 import java.io.File;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.regex.Pattern;
37 
38 public class SendBug {
39 
40     private static final String LOG_TAG = SendBug.class.getSimpleName();
41     private static final Pattern EMAIL_REGEX = Pattern.compile(
42             "^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$");
43     private static final String SEND_BUG_INTENT_ACTION = "android.testing.SEND_BUG";
44 
main(String[] args)45     public static void main(String[] args) {
46         if (args.length == 1) {
47             new SendBug().run(args[0]);
48         } else if (args.length == 2) {
49             new SendBug().run(args[0], args[1]);
50         }
51     }
52 
run(String bugreportPath)53     private void run(String bugreportPath) {
54         run(bugreportPath, null);
55     }
56 
run(String bugreportPath, String screenShotPath)57     private void run(String bugreportPath, String screenShotPath) {
58         final File bugreport = new File(bugreportPath);
59         File screenShot = null;
60         if (screenShotPath != null) {
61             screenShot = new File(screenShotPath);
62         }
63         final Uri bugreportUri = Uri.fromFile(bugreport);
64         // todo (aalbert): investigate adding a screenshot to BugReporter
65         Intent intent = tryBugReporter(bugreportUri);
66         if (intent == null) {
67             final Uri screenshotUri = screenShot != null
68                     ? Uri.fromFile(screenShot) : null;
69             intent = getSendMailIntent(bugreportUri, screenshotUri);
70         }
71         if (intent != null) {
72             final IActivityManager am = ActivityManagerNative.getDefault();
73             if (am == null) {
74                 Log.e(LOG_TAG, "Cannot get ActivityManager, is the system running?");
75                 return;
76             }
77             try {
78                 am.startActivityAsUser(null, intent, intent.getType(), null, null, 0, 0,
79                         null, null, null, UserHandle.USER_CURRENT);
80             } catch (RemoteException e) {
81                 // ignore
82             }
83         } else {
84             Log.w(LOG_TAG, "Cannot find account to send bugreport, local path: "
85                     + bugreportPath);
86         }
87     }
88 
tryBugReporter(Uri bugreportUri)89     private Intent tryBugReporter(Uri bugreportUri) {
90         final Intent intent = new Intent(SEND_BUG_INTENT_ACTION);
91         intent.setData(bugreportUri);
92         final IPackageManager pm = IPackageManager.Stub.asInterface(
93                 ServiceManager.getService("package"));
94         if (pm == null) {
95             Log.e(LOG_TAG, "Cannot get PackageManager, is the system running?");
96             return null;
97         }
98         final List<ResolveInfo> results;
99         try {
100             results = pm.queryIntentActivities(intent, null, 0, 0);
101         } catch (RemoteException e) {
102             return null;
103         }
104         if (results != null && results.size() > 0) {
105             final ResolveInfo info = results.get(0);
106             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
107             intent.setClassName(info.activityInfo.applicationInfo.packageName,
108                     info.activityInfo.name);
109             return intent;
110         } else {
111             return null;
112         }
113     }
114 
getSendMailIntent(Uri bugreportUri, Uri screenshotUri)115     private Intent getSendMailIntent(Uri bugreportUri, Uri screenshotUri) {
116         final Account sendToAccount = findSendToAccount();
117         final Intent intent = new Intent(Intent.ACTION_SEND);
118         intent.addCategory(Intent.CATEGORY_DEFAULT);
119         intent.setType("application/octet-stream");
120         intent.putExtra(Intent.EXTRA_SUBJECT, bugreportUri.getLastPathSegment());
121         final StringBuilder sb = new StringBuilder();
122         sb.append(SystemProperties.get("ro.build.description"));
123         sb.append("\n(Sent from BugMailer)");
124         intent.putExtra(Intent.EXTRA_TEXT, (CharSequence)sb);
125         if (screenshotUri != null) {
126             final ArrayList<Uri> attachments = new ArrayList<Uri>();
127             attachments.add(bugreportUri);
128             attachments.add(screenshotUri);
129             intent.setAction(Intent.ACTION_SEND_MULTIPLE);
130             intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
131         } else {
132             intent.putExtra(Intent.EXTRA_STREAM, bugreportUri);
133         }
134         if (sendToAccount != null) {
135             intent.putExtra(Intent.EXTRA_EMAIL, new String[]{sendToAccount.name});
136             return intent;
137         }
138         return null;
139     }
140 
findSendToAccount()141     private Account findSendToAccount() {
142         final IAccountManager accountManager = IAccountManager.Stub.asInterface(ServiceManager
143                 .getService(Context.ACCOUNT_SERVICE));
144         if (accountManager == null) {
145             Log.e(LOG_TAG, "Cannot get AccountManager, is the system running?");
146             return null;
147         }
148         Account[] accounts = null;
149         Account foundAccount = null;
150         String preferredDomain = SystemProperties.get("sendbug.preferred.domain");
151         if (!preferredDomain.startsWith("@")) {
152             preferredDomain = "@" + preferredDomain;
153         }
154         try {
155             accounts = accountManager.getAccounts(null);
156         } catch (RemoteException e) {
157             // ignore
158         }
159         if (accounts != null) {
160             for (Account account : accounts) {
161                 if (EMAIL_REGEX.matcher(account.name).matches()) {
162                     if (!preferredDomain.isEmpty()) {
163                         // if we have a preferred domain and it matches, return; otherwise keep
164                         // looking
165                         if (account.name.endsWith(preferredDomain)) {
166                             return account;
167                         } else {
168                             foundAccount = account;
169                         }
170                         // if we don't have a preferred domain, just return since it looks like
171                         // an email address
172                     } else {
173                         return account;
174                     }
175                 }
176             }
177         }
178         return foundAccount;
179     }
180 }
181