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.stream; 17 18 import android.content.ComponentName; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.ServiceConnection; 22 import android.os.IBinder; 23 import android.support.annotation.CallSuper; 24 import android.util.Log; 25 26 import java.util.Iterator; 27 import java.util.LinkedList; 28 import java.util.Queue; 29 30 /** 31 * A base class that produces {@link StreamCard} for the StreamService 32 */ 33 public abstract class StreamProducer { 34 private static final String TAG = "StreamProducer"; 35 36 protected final Context mContext; 37 38 /** 39 * A queue that holds {@link StreamCard}s that were added before this {@link StreamProducer} 40 * has connected to the {@link StreamService}. After connecting, these cards are posted to 41 * the StreamService. 42 */ 43 private final Queue<StreamCard> mQueuedCards = new LinkedList<>(); 44 45 private StreamService mStreamService; 46 StreamProducer(Context context)47 public StreamProducer(Context context) { 48 mContext = context; 49 } 50 51 /** 52 * Posts the given card to the {@link StreamService} for rendering by stream consumers. 53 * 54 * @return {@code true} if the card was successfully posted. {@code false} is returned if the 55 * {@link StreamService} is not available. The given card will be queued and posted when the 56 * {@link StreamService} becomes available. 57 */ postCard(StreamCard card)58 public final boolean postCard(StreamCard card) { 59 if (mStreamService != null) { 60 mStreamService.addStreamCard(card); 61 return true; 62 } 63 64 if (Log.isLoggable(TAG, Log.DEBUG)) { 65 Log.d(TAG, "StreamService not found, adding card to queue for later addition."); 66 } 67 68 mQueuedCards.add(card); 69 return false; 70 } 71 72 /** 73 * Removes the given card from the {@link StreamService}. If this {@link StreamProducer} has not 74 * connected to the {@link StreamService}, then {@link #mQueuedCards} is checked to see if it 75 * contains the given card. 76 * 77 * @return {@code true} if the card is successfully removed from either the 78 * {@link StreamService} or {@link #mQueuedCards}. 79 */ removeCard(StreamCard card)80 public final boolean removeCard(StreamCard card) { 81 if (card == null) { 82 return false; 83 } 84 85 if (mStreamService != null) { 86 mStreamService.removeStreamCard(card); 87 return true; 88 } 89 90 if (Log.isLoggable(TAG, Log.DEBUG)) { 91 Log.d(TAG, "StreamService not found, checking if it exists in the queue."); 92 } 93 94 for (Iterator<StreamCard> iterator = mQueuedCards.iterator(); iterator.hasNext();) { 95 StreamCard queuedCard = iterator.next(); 96 if (queuedCard.getType() == card.getType() && queuedCard.getId() == card.getId()) { 97 iterator.remove(); 98 return true; 99 } 100 } 101 102 return false; 103 } 104 onCardDismissed(StreamCard card)105 public void onCardDismissed(StreamCard card) { 106 // Handle when a StreamCard is dismissed. 107 if (Log.isLoggable(TAG, Log.DEBUG)) { 108 Log.d(TAG, "Stream Card dismissed: " + card); 109 } 110 } 111 112 /** 113 * Start the producer and connect to the {@link StreamService} 114 */ 115 @CallSuper start()116 public void start() { 117 Intent streamServiceIntent = new Intent(mContext, StreamService.class); 118 streamServiceIntent.setAction(StreamConstants.STREAM_PRODUCER_BIND_ACTION); 119 mContext.bindService(streamServiceIntent, mServiceConnection, 0 /* flags */); 120 } 121 122 /** 123 * Stop the producer. 124 */ 125 @CallSuper stop()126 public void stop() { 127 mContext.unbindService(mServiceConnection); 128 mQueuedCards.clear(); 129 } 130 131 private ServiceConnection mServiceConnection = new ServiceConnection() { 132 @Override 133 public void onServiceConnected(ComponentName name, IBinder service) { 134 StreamService.StreamProducerBinder binder 135 = (StreamService.StreamProducerBinder) service; 136 mStreamService = binder.getService(); 137 138 while (!mQueuedCards.isEmpty()) { 139 mStreamService.addStreamCard(mQueuedCards.remove()); 140 } 141 } 142 143 @Override 144 public void onServiceDisconnected(ComponentName name) { 145 mStreamService = null; 146 } 147 }; 148 } 149