dom/speakermanager/SpeakerManagerService.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:82a157db1a4d
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "SpeakerManagerService.h"
8 #include "SpeakerManagerServiceChild.h"
9 #include "mozilla/Services.h"
10 #include "mozilla/StaticPtr.h"
11 #include "mozilla/unused.h"
12 #include "mozilla/dom/ContentParent.h"
13 #include "nsIPropertyBag2.h"
14 #include "nsThreadUtils.h"
15 #include "nsServiceManagerUtils.h"
16 #include "AudioChannelService.h"
17 #include <cutils/properties.h>
18
19 #define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
20 #include "nsIAudioManager.h"
21
22 using namespace mozilla;
23 using namespace mozilla::dom;
24
25 StaticRefPtr<SpeakerManagerService> gSpeakerManagerService;
26
27 // static
28 SpeakerManagerService*
29 SpeakerManagerService::GetSpeakerManagerService()
30 {
31 MOZ_ASSERT(NS_IsMainThread());
32
33 if (XRE_GetProcessType() != GeckoProcessType_Default) {
34 return SpeakerManagerServiceChild::GetSpeakerManagerService();
35 }
36
37 // If we already exist, exit early
38 if (gSpeakerManagerService) {
39 return gSpeakerManagerService;
40 }
41
42 // Create new instance, register, return
43 nsRefPtr<SpeakerManagerService> service = new SpeakerManagerService();
44 NS_ENSURE_TRUE(service, nullptr);
45
46 gSpeakerManagerService = service;
47 return gSpeakerManagerService;
48 }
49
50 void
51 SpeakerManagerService::Shutdown()
52 {
53 if (XRE_GetProcessType() != GeckoProcessType_Default) {
54 return SpeakerManagerServiceChild::Shutdown();
55 }
56
57 if (gSpeakerManagerService) {
58 gSpeakerManagerService = nullptr;
59 }
60 }
61
62 NS_IMPL_ISUPPORTS(SpeakerManagerService, nsIObserver)
63
64 void
65 SpeakerManagerService::ForceSpeaker(bool aEnable, uint64_t aChildId)
66 {
67 TuruOnSpeaker(aEnable);
68 if (aEnable) {
69 mSpeakerStatusSet.Put(aChildId);
70 }
71 Notify();
72 return;
73 }
74
75 void
76 SpeakerManagerService::ForceSpeaker(bool aEnable, bool aVisible)
77 {
78 // b2g main process without oop
79 TuruOnSpeaker(aEnable && aVisible);
80 mVisible = aVisible;
81 mOrgSpeakerStatus = aEnable;
82 Notify();
83 }
84
85 void
86 SpeakerManagerService::TuruOnSpeaker(bool aOn)
87 {
88 nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
89 NS_ENSURE_TRUE_VOID(audioManager);
90 int32_t phoneState;
91 audioManager->GetPhoneState(&phoneState);
92 int32_t forceuse = (phoneState == nsIAudioManager::PHONE_STATE_IN_CALL ||
93 phoneState == nsIAudioManager::PHONE_STATE_IN_COMMUNICATION)
94 ? nsIAudioManager::USE_COMMUNICATION : nsIAudioManager::USE_MEDIA;
95 if (aOn) {
96 audioManager->SetForceForUse(forceuse, nsIAudioManager::FORCE_SPEAKER);
97 } else {
98 audioManager->SetForceForUse(forceuse, nsIAudioManager::FORCE_NONE);
99 }
100 }
101
102 bool
103 SpeakerManagerService::GetSpeakerStatus()
104 {
105 char propQemu[PROPERTY_VALUE_MAX];
106 property_get("ro.kernel.qemu", propQemu, "");
107 if (!strncmp(propQemu, "1", 1)) {
108 return mOrgSpeakerStatus;
109 }
110 nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
111 NS_ENSURE_TRUE(audioManager, false);
112 int32_t usage;
113 audioManager->GetForceForUse(nsIAudioManager::USE_MEDIA, &usage);
114 return usage == nsIAudioManager::FORCE_SPEAKER;
115 }
116
117 void
118 SpeakerManagerService::Notify()
119 {
120 // Parent Notify to all the child processes.
121 nsTArray<ContentParent*> children;
122 ContentParent::GetAll(children);
123 for (uint32_t i = 0; i < children.Length(); i++) {
124 unused << children[i]->SendSpeakerManagerNotify();
125 }
126
127 for (uint32_t i = 0; i < mRegisteredSpeakerManagers.Length(); i++) {
128 mRegisteredSpeakerManagers[i]->
129 DispatchSimpleEvent(NS_LITERAL_STRING("speakerforcedchange"));
130 }
131 }
132
133 void
134 SpeakerManagerService::SetAudioChannelActive(bool aIsActive)
135 {
136 if (!aIsActive && !mVisible) {
137 ForceSpeaker(!mOrgSpeakerStatus, mVisible);
138 }
139 }
140
141 NS_IMETHODIMP
142 SpeakerManagerService::Observe(nsISupports* aSubject, const char*
143 aTopic, const char16_t* aData)
144 {
145 if (!strcmp(aTopic, "ipc:content-shutdown")) {
146 nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
147 if (!props) {
148 NS_WARNING("ipc:content-shutdown message without property bag as subject");
149 return NS_OK;
150 }
151
152 uint64_t childID = 0;
153 nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
154 &childID);
155 if (NS_SUCCEEDED(rv)) {
156 // If the audio has paused by audiochannel,
157 // the enable flag should be false and don't need to handle.
158 if (mSpeakerStatusSet.Contains(childID)) {
159 TuruOnSpeaker(false);
160 mSpeakerStatusSet.Remove(childID);
161 }
162 if (mOrgSpeakerStatus) {
163 TuruOnSpeaker(!mOrgSpeakerStatus);
164 mOrgSpeakerStatus = false;
165 }
166 } else {
167 NS_WARNING("ipc:content-shutdown message without childID property");
168 }
169 }
170 return NS_OK;
171 }
172
173 SpeakerManagerService::SpeakerManagerService()
174 : mOrgSpeakerStatus(false),
175 mVisible(false)
176 {
177 MOZ_COUNT_CTOR(SpeakerManagerService);
178 if (XRE_GetProcessType() == GeckoProcessType_Default) {
179 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
180 if (obs) {
181 obs->AddObserver(this, "ipc:content-shutdown", false);
182 }
183 }
184 AudioChannelService* audioChannelService =
185 AudioChannelService::GetAudioChannelService();
186 if (audioChannelService) {
187 audioChannelService->RegisterSpeakerManager(this);
188 }
189 }
190
191 SpeakerManagerService::~SpeakerManagerService()
192 {
193 MOZ_COUNT_DTOR(SpeakerManagerService);
194 AudioChannelService* audioChannelService =
195 AudioChannelService::GetAudioChannelService();
196 if (audioChannelService)
197 audioChannelService->UnregisterSpeakerManager(this);
198 }

mercurial