summaryrefslogtreecommitdiffstats
path: root/src/com/android/car/stream/StreamProducer.java
blob: d4971fc9a710669539caf3b00ae7eb2cb3c595eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.car.stream;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.annotation.CallSuper;
import android.util.Log;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

/**
 * A base class that produces {@link StreamCard} for the StreamService
 */
public abstract class StreamProducer {
    private static final String TAG = "StreamProducer";

    protected final Context mContext;

    /**
     * A queue that holds {@link StreamCard}s that were added before this {@link StreamProducer}
     * has connected to the {@link StreamService}. After connecting, these cards are posted to
     * the StreamService.
     */
    private final Queue<StreamCard> mQueuedCards = new LinkedList<>();

    private StreamService mStreamService;

    public StreamProducer(Context context) {
        mContext = context;
    }

    /**
     * Posts the given card to the {@link StreamService} for rendering by stream consumers.
     *
     * @return {@code true} if the card was successfully posted. {@code false} is returned if the
     * {@link StreamService} is not available. The given card will be queued and posted when the
     * {@link StreamService} becomes available.
     */
    public final boolean postCard(StreamCard card) {
        if (mStreamService != null) {
            mStreamService.addStreamCard(card);
            return true;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "StreamService not found, adding card to queue for later addition.");
        }

        mQueuedCards.add(card);
        return false;
    }

    /**
     * Removes the given card from the {@link StreamService}. If this {@link StreamProducer} has not
     * connected to the {@link StreamService}, then {@link #mQueuedCards} is checked to see if it
     * contains the given card.
     *
     * @return {@code true} if the card is successfully removed from either the
     * {@link StreamService} or {@link #mQueuedCards}.
     */
    public final boolean removeCard(StreamCard card) {
        if (card == null) {
            return false;
        }

        if (mStreamService != null) {
            mStreamService.removeStreamCard(card);
            return true;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "StreamService not found, checking if it exists in the queue.");
        }

        for (Iterator<StreamCard> iterator = mQueuedCards.iterator(); iterator.hasNext();) {
            StreamCard queuedCard = iterator.next();
            if (queuedCard.getType() == card.getType() && queuedCard.getId() == card.getId()) {
                iterator.remove();
                return true;
            }
        }

        return false;
    }

    public void onCardDismissed(StreamCard card) {
        // Handle when a StreamCard is dismissed.
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Stream Card dismissed: " + card);
        }
    }

    /**
     * Start the producer and connect to the {@link StreamService}
     */
    @CallSuper
    public void start() {
        Intent streamServiceIntent = new Intent(mContext, StreamService.class);
        streamServiceIntent.setAction(StreamConstants.STREAM_PRODUCER_BIND_ACTION);
        mContext.bindService(streamServiceIntent, mServiceConnection, 0 /* flags */);
    }

    /**
     * Stop the producer.
     */
    @CallSuper
    public void stop() {
        mContext.unbindService(mServiceConnection);
        mQueuedCards.clear();
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            StreamService.StreamProducerBinder binder
                    = (StreamService.StreamProducerBinder) service;
            mStreamService = binder.getService();

            while (!mQueuedCards.isEmpty()) {
                mStreamService.addStreamCard(mQueuedCards.remove());
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mStreamService = null;
        }
    };
}