• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.car.bugreport;
17 
18 import android.os.Build;
19 import android.view.LayoutInflater;
20 import android.view.View;
21 import android.view.ViewGroup;
22 import android.widget.Button;
23 import android.widget.TextView;
24 
25 import androidx.recyclerview.widget.RecyclerView;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * Shows bugreport title, status, status message and user action buttons. "Upload to Google" button
32  * is enabled when the status is {@link Status#STATUS_PENDING_USER_ACTION}, "Move to USB" button is
33  * enabled only when status is  {@link Status#STATUS_PENDING_USER_ACTION} and USB device is plugged
34  * in.
35  */
36 public class BugInfoAdapter extends RecyclerView.Adapter<BugInfoAdapter.BugInfoViewHolder> {
37     static final int BUTTON_TYPE_UPLOAD = 0;
38     static final int BUTTON_TYPE_MOVE = 1;
39     static final int BUTTON_TYPE_ADD_AUDIO = 2;
40 
41     /** If bugreport TTL points go below this number, show a notice message. */
42     private static final int MIN_TTL_POINTS_TO_SHOW_NOTICE = 10;
43 
44     /** Provides a handler for click events. */
45     interface ItemClickedListener {
46         /**
47          * Handles click events differently depending on provided buttonType and
48          * uses additional information provided in metaBugReport.
49          *
50          * @param buttonType    One of {@link #BUTTON_TYPE_UPLOAD}, {@link #BUTTON_TYPE_MOVE} or
51          *                      {@link #BUTTON_TYPE_ADD_AUDIO}.
52          * @param metaBugReport Selected bugreport.
53          * @param holder        ViewHolder of the clicked item.
54          */
onItemClicked(int buttonType, MetaBugReport metaBugReport, BugInfoViewHolder holder)55         void onItemClicked(int buttonType, MetaBugReport metaBugReport, BugInfoViewHolder holder);
56     }
57 
58     /**
59      * Reference to each bug report info views.
60      */
61     static class BugInfoViewHolder extends RecyclerView.ViewHolder {
62         /** Title view */
63         TextView mTitleView;
64 
65         /** Status View */
66         TextView mStatusView;
67 
68         /** Message View */
69         TextView mMessageView;
70 
71         /** Expiration Notice View */
72         TextView mExpirationNoticeView;
73 
74         /** Move Button */
75         Button mMoveButton;
76 
77         /** Upload Button */
78         Button mUploadButton;
79 
80         /** Add Audio Button */
81         Button mAddAudioButton;
82 
BugInfoViewHolder(View v)83         BugInfoViewHolder(View v) {
84             super(v);
85             mTitleView = itemView.findViewById(R.id.bug_info_row_title);
86             mStatusView = itemView.findViewById(R.id.bug_info_row_status);
87             mMessageView = itemView.findViewById(R.id.bug_info_row_status_message);
88             mExpirationNoticeView = itemView.findViewById(R.id.bug_info_row_expiration_notice);
89             mMoveButton = itemView.findViewById(R.id.bug_info_move_button);
90             mUploadButton = itemView.findViewById(R.id.bug_info_upload_button);
91             mAddAudioButton = itemView.findViewById(R.id.bug_info_add_audio_button);
92         }
93     }
94 
95     private List<MetaBugReport> mDataset;
96     private final ItemClickedListener mItemClickedListener;
97     private final Config mConfig;
98 
BugInfoAdapter(ItemClickedListener itemClickedListener, Config config)99     BugInfoAdapter(ItemClickedListener itemClickedListener, Config config) {
100         mItemClickedListener = itemClickedListener;
101         mDataset = new ArrayList<>();
102         mConfig = config;
103         // Allow RecyclerView to efficiently update UI; getItemId() is implemented below.
104         setHasStableIds(true);
105     }
106 
107     @Override
onCreateViewHolder(ViewGroup parent, int viewType)108     public BugInfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
109         // create a new view
110         View v = LayoutInflater.from(parent.getContext())
111                 .inflate(R.layout.bug_info_view, parent, false);
112         return new BugInfoViewHolder(v);
113     }
114 
115     @Override
onBindViewHolder(BugInfoViewHolder holder, int position)116     public void onBindViewHolder(BugInfoViewHolder holder, int position) {
117         MetaBugReport bugReport = mDataset.get(position);
118         holder.mTitleView.setText(bugReport.getTitle());
119         holder.mStatusView.setText(Status.toString(bugReport.getStatus()));
120 
121         showOrHideMessageView(bugReport, holder);
122         showOrHideExpirationNotice(bugReport, holder);
123         showOrHideUploadButton(bugReport, holder);
124         showOrHideMoveButton(bugReport, holder);
125         showOrHideAddAudioButton(bugReport, holder);
126     }
127 
pendingUserAction(MetaBugReport bugReport)128     private boolean pendingUserAction(MetaBugReport bugReport) {
129         int bugReportStatus = bugReport.getStatus();
130         return bugReportStatus == Status.STATUS_PENDING_USER_ACTION.getValue()
131                 || bugReportStatus == Status.STATUS_MOVE_FAILED.getValue()
132                 || bugReportStatus == Status.STATUS_UPLOAD_FAILED.getValue();
133     }
134 
pendingAudioRecording(MetaBugReport bugReport)135     private boolean pendingAudioRecording(MetaBugReport bugReport) {
136         return bugReport.getStatus() == Status.STATUS_AUDIO_PENDING.getValue();
137     }
138 
showOrHideMessageView(MetaBugReport bugReport, BugInfoViewHolder holder)139     private void showOrHideMessageView(MetaBugReport bugReport, BugInfoViewHolder holder) {
140         holder.mMessageView.setText(bugReport.getStatusMessage());
141         if (bugReport.getStatusMessage().isEmpty()) {
142             holder.mMessageView.setVisibility(View.GONE);
143         } else {
144             holder.mMessageView.setVisibility(View.VISIBLE);
145         }
146     }
147 
showOrHideExpirationNotice(MetaBugReport bugReport, BugInfoViewHolder holder)148     private void showOrHideExpirationNotice(MetaBugReport bugReport, BugInfoViewHolder holder) {
149         if (bugReport.getTtlPoints() <= MIN_TTL_POINTS_TO_SHOW_NOTICE
150                 && BugStorageUtils.canBugReportBeExpired(bugReport.getStatus())) {
151             holder.mExpirationNoticeView.setVisibility(View.VISIBLE);
152         } else {
153             holder.mExpirationNoticeView.setVisibility(View.GONE);
154         }
155     }
156 
showOrHideUploadButton(MetaBugReport bugReport, BugInfoViewHolder holder)157     private void showOrHideUploadButton(MetaBugReport bugReport, BugInfoViewHolder holder) {
158         // Enable the upload button only for userdebug/eng builds.
159         if (pendingUserAction(bugReport) && Build.IS_DEBUGGABLE) {
160             holder.mUploadButton.setText(R.string.bugreport_upload_gcs_button_text);
161             holder.mUploadButton.setEnabled(true);
162             holder.mUploadButton.setVisibility(View.VISIBLE);
163             holder.mUploadButton.setOnClickListener(
164                     view -> mItemClickedListener.onItemClicked(BUTTON_TYPE_UPLOAD, bugReport,
165                             holder));
166         } else {
167             holder.mUploadButton.setVisibility(View.GONE);
168             holder.mUploadButton.setEnabled(false);
169         }
170     }
171 
showOrHideMoveButton(MetaBugReport bugReport, BugInfoViewHolder holder)172     private void showOrHideMoveButton(MetaBugReport bugReport, BugInfoViewHolder holder) {
173         if (pendingUserAction(bugReport)) {
174             holder.mMoveButton.setEnabled(true);
175             holder.mMoveButton.setVisibility(View.VISIBLE);
176             holder.mMoveButton.setOnClickListener(
177                     view -> mItemClickedListener.onItemClicked(BUTTON_TYPE_MOVE, bugReport,
178                             holder));
179         } else {
180             holder.mMoveButton.setEnabled(false);
181             holder.mMoveButton.setVisibility(View.GONE);
182         }
183     }
184 
showOrHideAddAudioButton(MetaBugReport bugReport, BugInfoViewHolder holder)185     private void showOrHideAddAudioButton(MetaBugReport bugReport, BugInfoViewHolder holder) {
186         boolean showButton = true;
187 
188         if (pendingAudioRecording(bugReport)) {
189             if (mConfig.isAutoUpload()) {
190                 holder.mAddAudioButton.setText(
191                         R.string.bugreport_add_audio_upload_button_text);
192             } else {
193                 holder.mAddAudioButton.setText(R.string.bugreport_add_audio_button_text);
194             }
195         } else if (pendingUserAction(bugReport)) {
196             holder.mAddAudioButton.setText(R.string.bugreport_replace_audio_button_text);
197         } else {
198             showButton = false;
199         }
200 
201         if (showButton) {
202             holder.mAddAudioButton.setEnabled(true);
203             holder.mAddAudioButton.setVisibility(View.VISIBLE);
204             holder.mAddAudioButton.setOnClickListener(view ->
205                     mItemClickedListener.onItemClicked(BUTTON_TYPE_ADD_AUDIO, bugReport, holder));
206         } else {
207             holder.mAddAudioButton.setEnabled(false);
208             holder.mAddAudioButton.setVisibility(View.GONE);
209         }
210     }
211 
212     /** Sets dataSet; it copies the list, because it modifies it in this adapter. */
setDataset(List<MetaBugReport> bugReports)213     void setDataset(List<MetaBugReport> bugReports) {
214         mDataset = new ArrayList<>(bugReports);
215         notifyDataSetChanged();
216     }
217 
218     /** Update a bug report in the data set. */
updateBugReportInDataSet(MetaBugReport bugReport, int position)219     void updateBugReportInDataSet(MetaBugReport bugReport, int position) {
220         if (position != RecyclerView.NO_POSITION) {
221             mDataset.set(position, bugReport);
222             notifyItemChanged(position);
223         }
224     }
225 
226     @Override
getItemId(int position)227     public long getItemId(int position) {
228         return mDataset.get(position).getId();
229     }
230 
231     @Override
getItemCount()232     public int getItemCount() {
233         return mDataset.size();
234     }
235 }
236