1 package com.android.car.media; 2 3 import android.app.PendingIntent; 4 import android.car.drivingstate.CarUxRestrictions; 5 import android.os.Bundle; 6 import android.util.Log; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.view.ViewGroup; 10 11 import androidx.annotation.NonNull; 12 import androidx.fragment.app.Fragment; 13 14 import com.android.car.apps.common.UxrButton; 15 import com.android.car.apps.common.UxrTextView; 16 import com.android.car.apps.common.util.CarPackageManagerUtils; 17 18 /** 19 * A {@link Fragment} that displays the playback state error. 20 */ 21 public class ErrorFragment extends Fragment { 22 private final String TAG = "ErrorFragment"; 23 24 private static final String ERROR_RESOLUTION_ACTION_MESSAGE = "ERROR_RESOLUTION_ACTION_MESSAGE"; 25 private static final String ERROR_RESOLUTION_ACTION_LABEL = "ERROR_RESOLUTION_ACTION_LABEL"; 26 private static final String ERROR_RESOLUTION_ACTION_INTENT = "ERROR_RESOLUTION_ACTION_INTENT"; 27 28 // mErrorMessageView is defined explicitly as a UxrTextView instead of a TextView to 29 // provide clarity as it may be misleading to assume that mErrorMessageView extends all TextView 30 // methods. In addition, it increases discoverability of runtime issues that may occur. 31 private UxrTextView mErrorMessageView; 32 private UxrButton mErrorButton; 33 34 private String mErrorMessageStr; 35 private String mErrorLabel; 36 private PendingIntent mPendingIntent; 37 newInstance(String message, String label, PendingIntent intent)38 public static ErrorFragment newInstance(String message, String label, PendingIntent intent) { 39 ErrorFragment fragment = new ErrorFragment(); 40 41 Bundle args = new Bundle(); 42 args.putString(ERROR_RESOLUTION_ACTION_MESSAGE, message); 43 args.putString(ERROR_RESOLUTION_ACTION_LABEL, label); 44 args.putParcelable(ERROR_RESOLUTION_ACTION_INTENT, intent); 45 fragment.setArguments(args); 46 47 return fragment; 48 } 49 50 @Override onCreateView(@onNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState)51 public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, 52 Bundle savedInstanceState) { 53 View view = inflater.inflate(R.layout.fragment_error, container, false); 54 55 mErrorMessageView = view.findViewById(R.id.error_message); 56 mErrorButton = view.findViewById(R.id.error_button); 57 58 Bundle args = getArguments(); 59 if (args != null) { 60 mErrorMessageStr = args.getString(ERROR_RESOLUTION_ACTION_MESSAGE); 61 mErrorLabel = args.getString(ERROR_RESOLUTION_ACTION_LABEL); 62 mPendingIntent = args.getParcelable(ERROR_RESOLUTION_ACTION_INTENT); 63 } 64 65 if (mErrorMessageStr == null) { 66 Log.e(TAG, "ErrorFragment does not have an error message"); 67 return view; 68 } 69 70 mErrorMessageView.setText(mErrorMessageStr); 71 72 // Only an error message is required. Fragments without a provided message and label 73 // have these elements omitted. 74 if (mErrorLabel != null && mPendingIntent != null) { 75 mErrorButton.setText(mErrorLabel); 76 77 boolean isDistractionOptimized = CarPackageManagerUtils.getInstance(getActivity()) 78 .isDistractionOptimized(getActivity().getPackageManager(), 79 mPendingIntent.getIntent()); 80 mErrorButton.setUxRestrictions(isDistractionOptimized 81 ? CarUxRestrictions.UX_RESTRICTIONS_BASELINE 82 : CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP); 83 84 mErrorButton.setOnClickListener(v -> { 85 try { 86 mPendingIntent.send(); 87 } catch (PendingIntent.CanceledException e) { 88 if (Log.isLoggable(TAG, Log.ERROR)) { 89 Log.e(TAG, "Pending intent canceled"); 90 } 91 } 92 }); 93 mErrorButton.setVisibility(View.VISIBLE); 94 } else { 95 mErrorButton.setVisibility(View.GONE); 96 } 97 98 return view; 99 } 100 } 101