• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 android.car.cluster.sample;
17 
18 import static android.car.cluster.CarInstrumentClusterManager.CATEGORY_NAVIGATION;
19 
20 import android.app.ActivityOptions;
21 import android.car.CarNotConnectedException;
22 import android.car.cluster.ClusterActivityState;
23 import android.graphics.Rect;
24 import android.hardware.display.DisplayManager;
25 import android.hardware.display.DisplayManager.DisplayListener;
26 import android.hardware.display.VirtualDisplay;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.support.v4.app.Fragment;
30 import android.util.Log;
31 import android.view.Display;
32 import android.view.LayoutInflater;
33 import android.view.Surface;
34 import android.view.SurfaceHolder;
35 import android.view.SurfaceHolder.Callback;
36 import android.view.SurfaceView;
37 import android.view.View;
38 import android.view.ViewGroup;
39 
40 public class NavigationFragment extends Fragment {
41     private final static String TAG = "Cluster.NavigationFragment";
42 
43     private SurfaceView mSurfaceView;
44     private DisplayManager mDisplayManager;
45     private Rect mUnobscuredBounds;
46 
47     // Static because we want to keep alive this virtual display when navigating through
48     // ViewPager (this fragment gets dynamically destroyed and created)
49     private static VirtualDisplay mVirtualDisplay;
50     private static int mRegisteredNavDisplayId = Display.INVALID_DISPLAY;
51 
NavigationFragment()52     public NavigationFragment() {
53         // Required empty public constructor
54     }
55 
56     private final DisplayListener mDisplayListener = new DisplayListener() {
57         @Override
58         public void onDisplayAdded(int displayId) {
59             int navDisplayId = getVirtualDisplayId();
60             Log.i(TAG, "onDisplayAdded, displayId: " + displayId
61                     + ", navigation display id: " + navDisplayId);
62 
63             if (navDisplayId == displayId) {
64                 try {
65                     getService().setClusterActivityLaunchOptions(
66                             CATEGORY_NAVIGATION,
67                             ActivityOptions.makeBasic()
68                                     .setLaunchDisplayId(displayId));
69                     mRegisteredNavDisplayId = displayId;
70 
71                     getService().setClusterActivityState(
72                             CATEGORY_NAVIGATION,
73                             ClusterActivityState.create(true, mUnobscuredBounds).toBundle());
74                 } catch (CarNotConnectedException e) {
75                     throw new IllegalStateException(
76                             "Failed to report nav activity cluster launch options", e);
77                 }
78             }
79         }
80 
81         @Override
82         public void onDisplayRemoved(int displayId) {
83             if (mRegisteredNavDisplayId == displayId) {
84                 try {
85                     mRegisteredNavDisplayId = Display.INVALID_DISPLAY;
86                     getService().setClusterActivityLaunchOptions(
87                             CATEGORY_NAVIGATION, null);
88                 } catch (CarNotConnectedException e) {
89                     // This can happen only during shutdown, ignore.
90                 }
91             }
92         }
93 
94         @Override
95         public void onDisplayChanged(int displayId) {}
96     };
97 
98     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)99     public View onCreateView(LayoutInflater inflater, ViewGroup container,
100                              Bundle savedInstanceState) {
101         Log.i(TAG, "onCreateView");
102         mDisplayManager = getActivity().getSystemService(DisplayManager.class);
103         mDisplayManager.registerDisplayListener(mDisplayListener, new Handler());
104 
105         // Inflate the layout for this fragment
106         View root = inflater.inflate(R.layout.fragment_navigation, container, false);
107 
108         mSurfaceView = root.findViewById(R.id.nav_surface);
109         mSurfaceView.getHolder().addCallback(new Callback() {
110             @Override
111             public void surfaceCreated(SurfaceHolder holder) {
112                 Log.i(TAG, "surfaceCreated, holder: " + holder);
113             }
114 
115             @Override
116             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
117                 Log.i(TAG, "surfaceChanged, holder: " + holder + ", size:" + width + "x" + height
118                         + ", format:" + format);
119 
120                 //Create dummy unobscured area to report to navigation activity.
121                 mUnobscuredBounds = new Rect(40, 0, width - 80, height - 40);
122 
123                 if (mVirtualDisplay == null) {
124                     mVirtualDisplay = createVirtualDisplay(holder.getSurface(), width, height);
125                 } else {
126                     mVirtualDisplay.setSurface(holder.getSurface());
127                 }
128             }
129 
130             @Override
131             public void surfaceDestroyed(SurfaceHolder holder) {
132                 Log.i(TAG, "surfaceDestroyed, holder: " + holder + ", detaching surface from"
133                         + " display, surface: " + holder.getSurface());
134                 // detaching surface is similar to turning off the display
135                 mVirtualDisplay.setSurface(null);
136             }
137         });
138 
139         return root;
140     }
141 
createVirtualDisplay(Surface surface, int width, int height)142     private VirtualDisplay createVirtualDisplay(Surface surface, int width, int height) {
143         Log.i(TAG, "createVirtualDisplay, surface: " + surface + ", width: " + width
144                 + "x" + height);
145         return mDisplayManager.createVirtualDisplay("Cluster-App-VD", width, height, 160, surface,
146                 DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
147     }
148 
149     @Override
onDestroy()150     public void onDestroy() {
151         super.onDestroy();
152         Log.i(TAG, "onDestroy");
153     }
154 
getService()155     private SampleClusterServiceImpl getService() {
156         return ((MainClusterActivity) getActivity()).getService();
157     }
158 
getVirtualDisplayId()159     private int getVirtualDisplayId() {
160         return (mVirtualDisplay != null && mVirtualDisplay.getDisplay() != null)
161                 ? mVirtualDisplay.getDisplay().getDisplayId() : Display.INVALID_DISPLAY;
162     }
163 }
164