1905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev/* 2905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * Copyright (C) 2017 The Android Open Source Project 3905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * 4905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * Licensed under the Apache License, Version 2.0 (the "License"); 5905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * you may not use this file except in compliance with the License. 6905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * You may obtain a copy of the License at 7905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * 8905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * http://www.apache.org/licenses/LICENSE-2.0 9905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * 10905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * Unless required by applicable law or agreed to in writing, software 11905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * distributed under the License is distributed on an "AS IS" BASIS, 12905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * See the License for the specific language governing permissions and 14905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev * limitations under the License. 15905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev */ 16905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevpackage android.car.cluster.sample; 17905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 18905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport static android.car.cluster.CarInstrumentClusterManager.CATEGORY_NAVIGATION; 19905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 20905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.app.ActivityOptions; 21905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.car.CarNotConnectedException; 22905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.car.cluster.ClusterActivityState; 23905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.graphics.Rect; 24905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.hardware.display.DisplayManager; 25905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.hardware.display.DisplayManager.DisplayListener; 26905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.hardware.display.VirtualDisplay; 27905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.os.Bundle; 28905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.os.Handler; 29905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.support.v4.app.Fragment; 30905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.util.Log; 31905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.Display; 32905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.LayoutInflater; 33905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.Surface; 34905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.SurfaceHolder; 35905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.SurfaceHolder.Callback; 36905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.SurfaceView; 37905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.View; 38905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevimport android.view.ViewGroup; 39905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 40905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsevpublic class NavigationFragment extends Fragment { 41905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private final static String TAG = "Cluster.NavigationFragment"; 42905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 43905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private SurfaceView mSurfaceView; 44905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private DisplayManager mDisplayManager; 45905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private Rect mUnobscuredBounds; 46905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 47905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // Static because we want to keep alive this virtual display when navigating through 48905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // ViewPager (this fragment gets dynamically destroyed and created) 49905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private static VirtualDisplay mVirtualDisplay; 50905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private static int mRegisteredNavDisplayId = Display.INVALID_DISPLAY; 51905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 52905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public NavigationFragment() { 53905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // Required empty public constructor 54905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 55905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 56905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private final DisplayListener mDisplayListener = new DisplayListener() { 57905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 58905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void onDisplayAdded(int displayId) { 59905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev int navDisplayId = getVirtualDisplayId(); 60905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "onDisplayAdded, displayId: " + displayId 61905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev + ", navigation display id: " + navDisplayId); 62905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 63905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev if (navDisplayId == displayId) { 64905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev try { 65905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev getService().setClusterActivityLaunchOptions( 66905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev CATEGORY_NAVIGATION, 67905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev ActivityOptions.makeBasic() 68905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev .setLaunchDisplayId(displayId)); 69905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mRegisteredNavDisplayId = displayId; 70905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 71905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev getService().setClusterActivityState( 72905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev CATEGORY_NAVIGATION, 73905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev ClusterActivityState.create(true, mUnobscuredBounds).toBundle()); 74905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } catch (CarNotConnectedException e) { 75905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev throw new IllegalStateException( 76905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev "Failed to report nav activity cluster launch options", e); 77905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 78905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 79905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 80905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 81905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 82905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void onDisplayRemoved(int displayId) { 83905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev if (mRegisteredNavDisplayId == displayId) { 84905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev try { 85905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mRegisteredNavDisplayId = Display.INVALID_DISPLAY; 86905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev getService().setClusterActivityLaunchOptions( 87905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev CATEGORY_NAVIGATION, null); 88905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } catch (CarNotConnectedException e) { 89905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // This can happen only during shutdown, ignore. 90905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 91905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 92905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 93905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 94905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 95905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void onDisplayChanged(int displayId) {} 96905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev }; 97905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 98905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 99905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public View onCreateView(LayoutInflater inflater, ViewGroup container, 100905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Bundle savedInstanceState) { 101905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "onCreateView"); 102905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mDisplayManager = getActivity().getSystemService(DisplayManager.class); 103905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mDisplayManager.registerDisplayListener(mDisplayListener, new Handler()); 104905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 105905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // Inflate the layout for this fragment 106905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev View root = inflater.inflate(R.layout.fragment_navigation, container, false); 107905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 108905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mSurfaceView = root.findViewById(R.id.nav_surface); 109905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mSurfaceView.getHolder().addCallback(new Callback() { 110905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 111905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void surfaceCreated(SurfaceHolder holder) { 112905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "surfaceCreated, holder: " + holder); 113905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 114905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 115905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 116905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 117905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "surfaceChanged, holder: " + holder + ", size:" + width + "x" + height 118905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev + ", format:" + format); 119905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 120905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev //Create dummy unobscured area to report to navigation activity. 121905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mUnobscuredBounds = new Rect(40, 0, width - 80, height - 40); 122905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 123905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev if (mVirtualDisplay == null) { 124905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mVirtualDisplay = createVirtualDisplay(holder.getSurface(), width, height); 125905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } else { 126905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mVirtualDisplay.setSurface(holder.getSurface()); 127905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 128905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 129905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 130905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 131905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void surfaceDestroyed(SurfaceHolder holder) { 132905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "surfaceDestroyed, holder: " + holder + ", detaching surface from" 133905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev + " display, surface: " + holder.getSurface()); 134905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev // detaching surface is similar to turning off the display 135905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev mVirtualDisplay.setSurface(null); 136905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 137905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev }); 138905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 139905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev return root; 140905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 141905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 142905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private VirtualDisplay createVirtualDisplay(Surface surface, int width, int height) { 143905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "createVirtualDisplay, surface: " + surface + ", width: " + width 144905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev + "x" + height); 145905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev return mDisplayManager.createVirtualDisplay("Cluster-App-VD", width, height, 160, surface, 146905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); 147905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 148905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 149905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev @Override 150905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev public void onDestroy() { 151905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev super.onDestroy(); 152905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev Log.i(TAG, "onDestroy"); 153905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 154905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 155905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private SampleClusterServiceImpl getService() { 156905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev return ((MainClusterActivity) getActivity()).getService(); 157905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 158905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev 159905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev private int getVirtualDisplayId() { 160905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev return (mVirtualDisplay != null && mVirtualDisplay.getDisplay() != null) 161905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev ? mVirtualDisplay.getDisplay().getDisplayId() : Display.INVALID_DISPLAY; 162905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev } 163905968cf95d4c8608d6d9351b5dd10fe994a1220Pavel Maltsev} 164