summaryrefslogtreecommitdiffstats
path: root/dom/system/gonk/ril_worker_telephony_request_queue.js
blob: 4dba7a42fbbf8dae6b59a8f7f2a68e0ea899c2eb (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
149
150
151
152
153
154
155
156
157
/* global DEBUG, DEBUG_WORKER */
/* global REQUEST_GET_CURRENT_CALLS */
/* global REQUEST_ANSWER, REQUEST_CONFERENCE, REQUEST_DIAL */
/* global REQUEST_DIAL_EMERGENCY_CALL, REQUEST_HANGUP */
/* global REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND */
/* global REQUEST_HANGUP_WAITING_OR_BACKGROUND */
/* global REQUEST_SEPARATE_CONNECTION */
/* global REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, REQUEST_UDUB */

"use strict";

(function(exports) {

  const TELEPHONY_REQUESTS = [
    REQUEST_GET_CURRENT_CALLS,
    REQUEST_ANSWER,
    REQUEST_CONFERENCE,
    REQUEST_DIAL,
    REQUEST_DIAL_EMERGENCY_CALL,
    REQUEST_HANGUP,
    REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
    REQUEST_HANGUP_WAITING_OR_BACKGROUND,
    REQUEST_SEPARATE_CONNECTION,
    REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
    REQUEST_UDUB
  ];

  // Set to true in ril_consts.js to see debug messages
  let DEBUG = DEBUG_WORKER;

  /**
   * Queue entry; only used in the queue.
   */
  let TelephonyRequestEntry = function(request, callback) {
    this.request = request;
    this.callback = callback;
  };

  let TelephonyRequestQueue = function(ril) {
    this.ril = ril;
    this.currentQueue = null;  // Point to the current running queue.

    this.queryQueue = [];
    this.controlQueue = [];
  };

  TelephonyRequestQueue.prototype._getQueue = function(request) {
    return (request === REQUEST_GET_CURRENT_CALLS) ? this.queryQueue
                                                   : this.controlQueue;
  };

  TelephonyRequestQueue.prototype._getAnotherQueue = function(queue) {
    return (this.queryQueue === queue) ? this.controlQueue : this.queryQueue;
  };

  TelephonyRequestQueue.prototype._find = function(queue, request) {
    for (let i = 0; i < queue.length; ++i) {
      if (queue[i].request === request) {
        return i;
      }
    }
    return -1;
  };

  TelephonyRequestQueue.prototype._startQueue = function(queue) {
    if (queue.length === 0) {
      return;
    }

    // We only need to keep one entry for queryQueue.
    if (queue === this.queryQueue) {
      queue.splice(1, queue.length - 1);
    }

    this.currentQueue = queue;
    for (let entry of queue) {
      this._executeEntry(entry);
    }
  };

  TelephonyRequestQueue.prototype._executeEntry = function(entry) {
    if (DEBUG) {
      this.debug("execute " + this._getRequestName(entry.request));
    }
    entry.callback();
  };

  TelephonyRequestQueue.prototype._getRequestName = function(request) {
    let method = this.ril[request];
    return (typeof method === 'function') ? method.name : "";
  };

  TelephonyRequestQueue.prototype.debug = function(msg) {
    this.ril.context.debug("[TeleQ] " + msg);
  };

  TelephonyRequestQueue.prototype.isValidRequest = function(request) {
    return TELEPHONY_REQUESTS.indexOf(request) !== -1;
  };

  TelephonyRequestQueue.prototype.push = function(request, callback) {
    if (!this.isValidRequest(request)) {
      if (DEBUG) {
        this.debug("Error: " + this._getRequestName(request) +
                   " is not a telephony request");
      }
      return;
    }

    if (DEBUG) {
      this.debug("push " + this._getRequestName(request));
    }
    let entry = new TelephonyRequestEntry(request, callback);
    let queue = this._getQueue(request);
    queue.push(entry);

    // Try to run the request.
    if (this.currentQueue === queue) {
      this._executeEntry(entry);
    } else if (!this.currentQueue) {
      this._startQueue(queue);
    }
  };

  TelephonyRequestQueue.prototype.pop = function(request) {
    if (!this.isValidRequest(request)) {
      if (DEBUG) {
        this.debug("Error: " + this._getRequestName(request) +
                   " is not a telephony request");
      }
      return;
    }

    if (DEBUG) {
      this.debug("pop " + this._getRequestName(request));
    }
    let queue = this._getQueue(request);
    let index = this._find(queue, request);
    if (index === -1) {
      throw new Error("Cannot find the request in telephonyRequestQueue.");
    } else {
      queue.splice(index, 1);
    }

    if (queue.length === 0) {
      this.currentQueue = null;
      this._startQueue(this._getAnotherQueue(queue));
    }
  };


  // Before we make sure to form it as a module would not add extra
  // overhead of module loading, we need to define it in this way
  // rather than 'module.exports' it as a module component.
  exports.TelephonyRequestQueue = TelephonyRequestQueue;
})(self); // in worker self is the global