• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.server.uwb;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.os.Binder;
22 import android.os.BugreportManager;
23 import android.os.BugreportParams;
24 import android.util.Log;
25 
26 /**
27  * A class to trigger bugreport and other logs for UWB related failures
28  */
29 public class UwbDiagnostics {
30     private static final  String TAG = "UwbDiagnostics";
31     private final Context mContext;
32     private final SystemBuildProperties mSystemBuildProperties;
33     private final UwbInjector mUwbInjector;
34     private long mLastBugReportTimeMs;
UwbDiagnostics( Context context, UwbInjector uwbInjector, SystemBuildProperties systemBuildProperties)35     public UwbDiagnostics(
36             Context context, UwbInjector uwbInjector, SystemBuildProperties systemBuildProperties) {
37         mContext = context;
38         mSystemBuildProperties = systemBuildProperties;
39         mUwbInjector = uwbInjector;
40     }
41 
42     /**
43      * Take a bug report if it is in user debug build and there is no recent bug report
44      */
takeBugReport(String bugTitle)45     public void takeBugReport(String bugTitle) {
46         if (!mSystemBuildProperties.isUserdebugBuild()) {
47             Log.d(TAG, "Skip bugreport because it can be triggered only in userDebug build");
48             return;
49         }
50         long currentTimeMs = mUwbInjector.getElapsedSinceBootMillis();
51         long timeSinceLastUploadMs = currentTimeMs - mLastBugReportTimeMs;
52         if (timeSinceLastUploadMs
53                 < mUwbInjector.getDeviceConfigFacade().getBugReportMinIntervalMs()
54                 && mLastBugReportTimeMs > 0) {
55             Log.d(TAG, "Bugreport was filed recently, Skip " + bugTitle);
56             return;
57         }
58 
59         if (!takeBugreportThroughBetterBug(bugTitle)) {
60             takeBugreportThroughBugreportManager(bugTitle);
61         }
62     }
63 
takeBugreportThroughBetterBug(String bugTitle)64     private boolean takeBugreportThroughBetterBug(String bugTitle) {
65         Intent launchBetterBugIntent =
66                 new BetterBugIntentBuilder()
67                         .setIssueTitle(bugTitle)
68                         .setHappenedTimestamp(System.currentTimeMillis())
69                         .build();
70         boolean isIntentUnSafe = mContext
71                 .getPackageManager().queryIntentActivities(launchBetterBugIntent, 0)
72                 .isEmpty();
73         if (isIntentUnSafe) {
74             Log.d(TAG, "intent is unsafe and skip bugreport from betterBug: " + bugTitle);
75             return false;
76         }
77 
78         long identity = Binder.clearCallingIdentity();
79         try {
80             launchBetterBugIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
81             mContext.startActivity(launchBetterBugIntent);
82             Log.d(TAG, "Taking the bugreport through betterBug: " + bugTitle);
83             mLastBugReportTimeMs = mUwbInjector.getElapsedSinceBootMillis();
84             return true;
85         } catch (RuntimeException e) {
86             Log.e(TAG, "Error taking bugreport: " + e);
87             return false;
88         } finally {
89             Binder.restoreCallingIdentity(identity);
90         }
91     }
92 
takeBugreportThroughBugreportManager(String bugTitle)93     private boolean takeBugreportThroughBugreportManager(String bugTitle) {
94         BugreportManager bugreportManager = mContext.getSystemService(BugreportManager.class);
95         BugreportParams params = new BugreportParams(BugreportParams.BUGREPORT_MODE_FULL);
96         try {
97             bugreportManager.requestBugreport(params, bugTitle, bugTitle);
98             Log.d(TAG, "Taking the bugreport through bugreportManager: " + bugTitle);
99             mLastBugReportTimeMs = mUwbInjector.getElapsedSinceBootMillis();
100             return true;
101         } catch (RuntimeException e) {
102             Log.e(TAG, "Error taking bugreport: " + e);
103             return false;
104         }
105     }
106 
107     /**
108      * @return the last time when the bug report is taken
109      */
getLastBugReportTimeMs()110     long getLastBugReportTimeMs() {
111         return mLastBugReportTimeMs;
112     }
113 
114     /**
115      * Builder for communicating with the betterbug.
116      */
117     private class BetterBugIntentBuilder {
118 
119         private static final String ACTION_FILE_BUG_DEEPLINK =
120                 "com.google.android.apps.betterbug.intent.FILE_BUG_DEEPLINK";
121         private static final boolean DEFAULT_AUTO_UPLOAD_ENABLED = false;
122         private static final boolean DEFAULT_BUGREPORT_REQUIRED = true;
123         private static final String DEFAULT_BUG_ASSIGNEE = "android-uwb-team@google.com";
124         private static final long DEFAULT_COMPONENT_ID = 1042770L;
125 
126         private static final String EXTRA_DEEPLINK = "EXTRA_DEEPLINK";
127         private static final String EXTRA_ISSUE_TITLE = "EXTRA_ISSUE_TITLE";
128         private static final String EXTRA_DEEPLINK_SILENT = "EXTRA_DEEPLINK_SILENT";
129         private static final String EXTRA_ADDITIONAL_COMMENT = "EXTRA_ADDITIONAL_COMMENT";
130         private static final String EXTRA_TARGET_PACKAGE = "EXTRA_TARGET_PACKAGE";
131         private static final String EXTRA_REQUIRE_BUGREPORT = "EXTRA_REQUIRE_BUGREPORT";
132         private static final String EXTRA_HAPPENED_TIME = "EXTRA_HAPPENED_TIME";
133         private static final String EXTRA_BUG_ASSIGNEE = "EXTRA_BUG_ASSIGNEE";
134         private static final String EXTRA_COMPONENT_ID = "EXTRA_COMPONENT_ID";
135 
136         private final Intent mBetterBugIntent;
137 
BetterBugIntentBuilder()138         BetterBugIntentBuilder() {
139             mBetterBugIntent = new Intent().setAction(ACTION_FILE_BUG_DEEPLINK)
140                     .putExtra(EXTRA_DEEPLINK, true);
141             setAutoUpload(DEFAULT_AUTO_UPLOAD_ENABLED);
142             setBugreportRequired(DEFAULT_BUGREPORT_REQUIRED);
143             setBugAssignee(DEFAULT_BUG_ASSIGNEE);
144             setComponentId(DEFAULT_COMPONENT_ID);
145         }
146 
setIssueTitle(String title)147         public BetterBugIntentBuilder setIssueTitle(String title) {
148             mBetterBugIntent.putExtra(EXTRA_ISSUE_TITLE, title);
149             return this;
150         }
151 
setAutoUpload(boolean autoUploadEnabled)152         public BetterBugIntentBuilder setAutoUpload(boolean autoUploadEnabled) {
153             mBetterBugIntent.putExtra(EXTRA_DEEPLINK_SILENT, autoUploadEnabled);
154             return this;
155         }
156 
setTargetPackage(String targetPackage)157         public BetterBugIntentBuilder setTargetPackage(String targetPackage) {
158             mBetterBugIntent.putExtra(EXTRA_TARGET_PACKAGE, targetPackage);
159             return this;
160         }
161 
setComponentId(long componentId)162         public BetterBugIntentBuilder setComponentId(long componentId) {
163             mBetterBugIntent.putExtra(EXTRA_COMPONENT_ID, componentId);
164             return this;
165         }
166 
setBugreportRequired(boolean isBugreportRequired)167         public BetterBugIntentBuilder setBugreportRequired(boolean isBugreportRequired) {
168             mBetterBugIntent.putExtra(EXTRA_REQUIRE_BUGREPORT, isBugreportRequired);
169             return this;
170         }
171 
setHappenedTimestamp(long happenedTimeSinceEpochMs)172         public BetterBugIntentBuilder setHappenedTimestamp(long happenedTimeSinceEpochMs) {
173             mBetterBugIntent.putExtra(EXTRA_HAPPENED_TIME, happenedTimeSinceEpochMs);
174             return this;
175         }
176 
setAdditionalComment(String additionalComment)177         public BetterBugIntentBuilder setAdditionalComment(String additionalComment) {
178             mBetterBugIntent.putExtra(EXTRA_ADDITIONAL_COMMENT, additionalComment);
179             return this;
180         }
181 
setBugAssignee(String assignee)182         public BetterBugIntentBuilder setBugAssignee(String assignee) {
183             mBetterBugIntent.putExtra(EXTRA_BUG_ASSIGNEE, assignee);
184             return this;
185         }
186 
build()187         public Intent build() {
188             return mBetterBugIntent;
189         }
190     }
191 }
192