blob: 251b670c4e8b763f5a14aa00254937db765e4319 [file] [log] [blame]
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -08001/*
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 */
Pavel Maltsev0477e292016-05-27 12:22:36 -070016package android.car.cluster.renderer;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080017
18import android.annotation.Nullable;
Pavel Maltsev8cf86912016-04-01 18:01:51 -070019import android.car.navigation.CarNavigationInstrumentCluster;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080020import android.graphics.Bitmap;
Pavel Maltsev1fd2ff62017-07-05 19:09:07 -070021import android.os.Bundle;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080022import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
25
Pavel Maltsev0477e292016-05-27 12:22:36 -070026import java.lang.ref.WeakReference;
Pavel Maltsev8cf86912016-04-01 18:01:51 -070027import java.util.concurrent.CountDownLatch;
28
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080029/**
30 * A wrapper over {@link NavigationRenderer} that runs all its methods in the context of provided
31 * looper. It is guaranteed that all calls will be invoked in order they were called.
32 */
Dean Harding8099f2f2018-02-07 15:00:21 -080033// TODO(deanh): Does this class even need to exist?
Pavel Maltsev0477e292016-05-27 12:22:36 -070034/* package */ class ThreadSafeNavigationRenderer extends NavigationRenderer {
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080035
36 private final Handler mHandler;
Pavel Maltsev8cf86912016-04-01 18:01:51 -070037 private final NavigationRenderer mRenderer;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080038
Dean Harding8099f2f2018-02-07 15:00:21 -080039 private final static int MSG_EVENT = 1;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080040
41 /** Creates thread-safe {@link NavigationRenderer}. Returns null if renderer == null */
42 @Nullable
Pavel Maltsev0477e292016-05-27 12:22:36 -070043 static NavigationRenderer createFor(Looper looper, NavigationRenderer renderer) {
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080044 return renderer == null ? null : new ThreadSafeNavigationRenderer(looper, renderer);
45 }
46
47 private ThreadSafeNavigationRenderer(Looper looper, NavigationRenderer renderer) {
Pavel Maltsev8cf86912016-04-01 18:01:51 -070048 mRenderer = renderer;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080049 mHandler = new NavigationRendererHandler(looper, renderer);
50 }
51
52 @Override
Pavel Maltsev8cf86912016-04-01 18:01:51 -070053 public CarNavigationInstrumentCluster getNavigationProperties() {
Pavel Maltsev0477e292016-05-27 12:22:36 -070054 if (mHandler.getLooper() == Looper.myLooper()) {
55 return mRenderer.getNavigationProperties();
56 } else {
57 return runAndWaitResult(mHandler,
58 new RunnableWithResult<CarNavigationInstrumentCluster>() {
59 @Override
60 protected CarNavigationInstrumentCluster createResult() {
61 return mRenderer.getNavigationProperties();
62 }
63 });
64 }
Pavel Maltsev8cf86912016-04-01 18:01:51 -070065 }
66
67 @Override
Pavel Maltsev1fd2ff62017-07-05 19:09:07 -070068 public void onEvent(int eventType, Bundle bundle) {
69 mHandler.sendMessage(mHandler.obtainMessage(MSG_EVENT, eventType, 0, bundle));
70 }
71
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080072 private static class NavigationRendererHandler extends RendererHandler<NavigationRenderer> {
73
74 NavigationRendererHandler(Looper looper, NavigationRenderer renderer) {
75 super(looper, renderer);
76 }
77
78 @Override
79 public void handleMessage(Message msg, NavigationRenderer renderer) {
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080080 switch (msg.what) {
Pavel Maltsev1fd2ff62017-07-05 19:09:07 -070081 case MSG_EVENT:
82 Bundle bundle = (Bundle) msg.obj;
83 renderer.onEvent(msg.arg1, bundle);
84 break;
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -080085 default:
86 throw new IllegalArgumentException("Msg: " + msg.what);
87 }
88 }
89 }
90
Jason Tholstrup6ad2b512016-07-14 14:27:37 -070091 private static <E> E runAndWaitResult(Handler handler, final RunnableWithResult<E> runnable) {
Pavel Maltsev0477e292016-05-27 12:22:36 -070092 final CountDownLatch latch = new CountDownLatch(1);
Jason Tholstrup6ad2b512016-07-14 14:27:37 -070093
94 Runnable wrappedRunnable = new Runnable() {
95 @Override
96 public void run() {
97 runnable.run();
98 latch.countDown();
99 }
100 };
101
102 handler.post(wrappedRunnable);
103
Pavel Maltsev8cf86912016-04-01 18:01:51 -0700104 try {
Pavel Maltsev0477e292016-05-27 12:22:36 -0700105 latch.await();
Pavel Maltsev8cf86912016-04-01 18:01:51 -0700106 } catch (InterruptedException e) {
107 throw new RuntimeException(e);
108 }
109 return runnable.getResult();
110 }
111
Pavel Maltsev0477e292016-05-27 12:22:36 -0700112 private static abstract class RunnableWithResult<T> implements Runnable {
Pavel Maltsev8cf86912016-04-01 18:01:51 -0700113 private volatile T result;
114
115 protected abstract T createResult();
116
117 @Override
118 public void run() {
119 result = createResult();
120 }
121
122 public T getResult() {
123 return result;
124 }
125 }
Pavel Maltsev0477e292016-05-27 12:22:36 -0700126
127 private static abstract class RendererHandler<T> extends Handler {
128
129 private final WeakReference<T> mRendererRef;
130
131 RendererHandler(Looper looper, T renderer) {
132 super(looper);
133 mRendererRef = new WeakReference<>(renderer);
134 }
135
136 @Override
137 public void handleMessage(Message msg) {
138 T renderer = mRendererRef.get();
139 if (renderer != null) {
140 handleMessage(msg, renderer);
141 }
142 }
143
144 public abstract void handleMessage(Message msg, T renderer);
145 }
Pavel Maltsev1ecdd6c2016-03-02 16:33:44 -0800146}