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.google.android.car.kitchensink.projection;
17 
18 import android.car.CarProjectionManager;
19 import android.car.CarProjectionManager.ProjectionStatusListener;
20 import android.car.projection.ProjectionStatus;
21 import android.os.Bundle;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.LinearLayout;
26 import android.widget.TextView;
27 
28 import androidx.fragment.app.Fragment;
29 
30 import com.google.android.car.kitchensink.KitchenSinkActivity;
31 import com.google.android.car.kitchensink.R;
32 import com.google.common.collect.ImmutableMap;
33 
34 import java.util.List;
35 
36 /**
37  * Reports information about the current projection status.
38  */
39 public class ProjectionFragment extends Fragment {
40     private KitchenSinkActivity mActivity;
41     private CarProjectionManager mCarProjectionManager;
42 
43     private TextView mCurrentProjectionStatus;
44     private TextView mCurrentProjectionPackage;
45     private LinearLayout mCurrentProjectionDetails;
46 
47     private static final ImmutableMap<Integer, String> STATE_TO_STRING = ImmutableMap.of(
48             ProjectionStatus.PROJECTION_STATE_INACTIVE, "Inactive",
49             ProjectionStatus.PROJECTION_STATE_READY_TO_PROJECT, "Ready to project",
50             ProjectionStatus.PROJECTION_STATE_ACTIVE_FOREGROUND, "Foreground",
51             ProjectionStatus.PROJECTION_STATE_ACTIVE_BACKGROUND, "Background");
52 
53     private static final ImmutableMap<Integer, String> TRANSPORT_TO_STRING = ImmutableMap.of(
54             ProjectionStatus.PROJECTION_TRANSPORT_NONE, "None",
55             ProjectionStatus.PROJECTION_TRANSPORT_USB, "USB",
56             ProjectionStatus.PROJECTION_TRANSPORT_WIFI, "WiFi");
57 
58     private class KitchenSinkProjectionStatusListener implements ProjectionStatusListener {
59         @Override
onProjectionStatusChanged( int state, String packageName, List<ProjectionStatus> details)60         public void onProjectionStatusChanged(
61                 int state,
62                 String packageName,
63                 List<ProjectionStatus> details) {
64             mCurrentProjectionStatus.setText(STATE_TO_STRING.get(state));
65             mCurrentProjectionPackage.setText(packageName);
66             mCurrentProjectionDetails.removeAllViews();
67             for (ProjectionStatus detail : details) {
68                 LinearLayout detailLayout =
69                         (LinearLayout)
70                                 getLayoutInflater()
71                                         .inflate(R.layout.projection_status_details, null);
72 
73                 TextView detailPackage = detailLayout.findViewById(R.id.projection_detail_package);
74                 detailPackage.setText(detail.getPackageName());
75 
76                 TextView detailState = detailLayout.findViewById(R.id.projection_detail_state);
77                 detailState.setText(STATE_TO_STRING.get(detail.getState()));
78 
79                 TextView detailTransport =
80                         detailLayout.findViewById(R.id.projection_detail_transport);
81                 detailTransport.setText(TRANSPORT_TO_STRING.get(detail.getTransport()));
82 
83                 for (ProjectionStatus.MobileDevice device : detail.getConnectedMobileDevices()) {
84                     LinearLayout deviceLayout =
85                             (LinearLayout)
86                                     getLayoutInflater()
87                                             .inflate(R.layout.projection_status_device, null);
88 
89                     TextView deviceId = deviceLayout.findViewById(R.id.projection_device_id);
90                     deviceId.setText(String.valueOf(device.getId()));
91 
92                     TextView deviceName = deviceLayout.findViewById(R.id.projection_device_name);
93                     deviceName.setText(device.getName());
94 
95                     LinearLayout deviceTransports =
96                             deviceLayout.findViewById(R.id.projection_device_transports);
97                     for (Integer transport : device.getAvailableTransports()) {
98                         TextView transportView = new TextView(mActivity);
99                         transportView.setText(TRANSPORT_TO_STRING.get(transport));
100 
101                         deviceTransports.addView(transportView);
102                     }
103 
104                     TextView deviceProjecting =
105                             deviceLayout.findViewById(R.id.projection_device_projecting);
106                     deviceProjecting.setText(String.valueOf(device.isProjecting()));
107 
108                     detailLayout.addView(deviceLayout);
109                 }
110                 mCurrentProjectionDetails.addView(detailLayout);
111             }
112         }
113     }
114 
115     private final KitchenSinkProjectionStatusListener mProjectionListener =
116             new KitchenSinkProjectionStatusListener();
117 
118     @Override
onCreate(Bundle savedInstanceState)119     public void onCreate(Bundle savedInstanceState) {
120         mActivity = (KitchenSinkActivity) getActivity();
121         mCarProjectionManager = mActivity.getProjectionManager();
122         super.onCreate(savedInstanceState);
123     }
124 
125     @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)126     public View onCreateView(
127             LayoutInflater inflater,
128             ViewGroup container,
129             Bundle savedInstanceState) {
130         View layout = inflater.inflate(R.layout.projection_status, container, false);
131 
132         mCurrentProjectionStatus = (TextView) layout.findViewById(R.id.current_projection_status);
133         mCurrentProjectionPackage = (TextView) layout.findViewById(R.id.current_projection_package);
134         mCurrentProjectionDetails =
135                 (LinearLayout) layout.findViewById(R.id.current_projection_details);
136 
137         return layout;
138     }
139 
140     @Override
onStart()141     public void onStart() {
142         mCarProjectionManager.registerProjectionStatusListener(mProjectionListener);
143         super.onStart();
144     }
145 
146     @Override
onStop()147     public void onStop() {
148         mCarProjectionManager.unregisterProjectionStatusListener(mProjectionListener);
149         super.onStop();
150     }
151 }
152