1 /* 2 * Copyright (C) 2016 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.cluster.renderer; 17 18 import android.annotation.Nullable; 19 import android.car.cluster.renderer.NavigationRenderer; 20 import android.graphics.Bitmap; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Message; 24 25 /** 26 * A wrapper over {@link NavigationRenderer} that runs all its methods in the context of provided 27 * looper. It is guaranteed that all calls will be invoked in order they were called. 28 */ 29 public class ThreadSafeNavigationRenderer extends NavigationRenderer { 30 31 private final Handler mHandler; 32 33 private final static int MSG_NAV_START = 1; 34 private final static int MSG_NAV_STOP = 2; 35 private final static int MSG_NAV_NEXT_TURN = 3; 36 private final static int MSG_NAV_NEXT_TURN_DISTANCE = 4; 37 38 /** Creates thread-safe {@link NavigationRenderer}. Returns null if renderer == null */ 39 @Nullable createFor(Looper looper, NavigationRenderer renderer)40 public static NavigationRenderer createFor(Looper looper, NavigationRenderer renderer) { 41 return renderer == null ? null : new ThreadSafeNavigationRenderer(looper, renderer); 42 } 43 ThreadSafeNavigationRenderer(Looper looper, NavigationRenderer renderer)44 private ThreadSafeNavigationRenderer(Looper looper, NavigationRenderer renderer) { 45 mHandler = new NavigationRendererHandler(looper, renderer); 46 } 47 48 @Override onStartNavigation()49 public void onStartNavigation() { 50 mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_START)); 51 } 52 53 @Override onStopNavigation()54 public void onStopNavigation() { 55 mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_STOP)); 56 } 57 58 @Override onNextTurnChanged(int event, String road, int turnAngle, int turnNumber, Bitmap image, int turnSide)59 public void onNextTurnChanged(int event, String road, int turnAngle, int turnNumber, 60 Bitmap image, int turnSide) { 61 mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_NEXT_TURN, 62 new NextTurn(event, road, turnAngle, turnNumber, image, turnSide))); 63 } 64 65 @Override onNextTurnDistanceChanged(int distanceMeters, int timeSeconds)66 public void onNextTurnDistanceChanged(int distanceMeters, int timeSeconds) { 67 mHandler.sendMessage(mHandler.obtainMessage( 68 MSG_NAV_NEXT_TURN_DISTANCE, distanceMeters, timeSeconds)); 69 } 70 71 private static class NavigationRendererHandler extends RendererHandler<NavigationRenderer> { 72 NavigationRendererHandler(Looper looper, NavigationRenderer renderer)73 NavigationRendererHandler(Looper looper, NavigationRenderer renderer) { 74 super(looper, renderer); 75 } 76 77 @Override handleMessage(Message msg, NavigationRenderer renderer)78 public void handleMessage(Message msg, NavigationRenderer renderer) { 79 80 switch (msg.what) { 81 case MSG_NAV_START: 82 renderer.onStartNavigation(); 83 break; 84 case MSG_NAV_STOP: 85 renderer.onStopNavigation(); 86 break; 87 case MSG_NAV_NEXT_TURN: 88 NextTurn nt = (NextTurn) msg.obj; 89 renderer.onNextTurnChanged(nt.event, nt.road, nt.turnAngle, nt.turnNumber, 90 nt.bitmap, nt.turnSide); 91 break; 92 case MSG_NAV_NEXT_TURN_DISTANCE: 93 renderer.onNextTurnDistanceChanged(msg.arg1, msg.arg2); 94 break; 95 default: 96 throw new IllegalArgumentException("Msg: " + msg.what); 97 } 98 } 99 } 100 101 private static class NextTurn { 102 private final int event; 103 private final String road; 104 private final int turnAngle; 105 private final int turnNumber; 106 private final Bitmap bitmap; 107 private final int turnSide; 108 NextTurn(int event, String road, int turnAngle, int turnNumber, Bitmap bitmap, int turnSide)109 NextTurn(int event, String road, int turnAngle, int turnNumber, Bitmap bitmap, 110 int turnSide) { 111 this.event = event; 112 this.road = road; 113 this.turnAngle = turnAngle; 114 this.turnNumber = turnNumber; 115 this.bitmap = bitmap; 116 this.turnSide = turnSide; 117 } 118 } 119 } 120