11/*
2- * Copyright (c) 2019 Livio, Inc.
2+ * Copyright (c) 2019-2020 Livio, Inc.
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
5454import com .smartdevicelink .transport .enums .TransportType ;
5555import com .smartdevicelink .util .DebugTool ;
5656
57+ import java .lang .ref .WeakReference ;
5758import java .util .ArrayList ;
5859import java .util .Collections ;
59- import java .util .concurrent .Callable ;
60- import java .util .concurrent .Executors ;
61- import java .util .concurrent .FutureTask ;
62- import java .util .concurrent .ScheduledExecutorService ;
6360
6461/**
6562 * The lifecycle manager creates a central point for all SDL session logic to converge. It should only be used by
6663 * the library itself. Usage outside the library is not permitted and will not be protected for in the future.
6764 *
68- * @author Bilal Alsharifi.
6965 */
7066@ RestrictTo (RestrictTo .Scope .LIBRARY )
7167public class LifecycleManager extends BaseLifecycleManager {
72- private static final int RESPONSE_WAIT_TIME = 2000 ;
73- private ISdlServiceListener navServiceListener ;
74- private boolean navServiceStartResponseReceived = false ;
75- private boolean navServiceStartResponse = false ;
76- private boolean navServiceEndResponseReceived = false ;
77- private boolean navServiceEndResponse = false ;
78- private boolean pcmServiceEndResponseReceived = false ;
79- private boolean pcmServiceEndResponse = false ;
80- private Context context ;
68+ private ISdlServiceListener videoServiceListener ;
69+ private boolean videoServiceStartResponseReceived = false ;
70+ private boolean videoServiceStartResponse = false ;
71+ private WeakReference <Context > contextWeakReference ;
8172
8273 public LifecycleManager (AppConfig appConfig , BaseTransportConfig config , LifecycleListener listener ) {
8374 super (appConfig , config , listener );
8475 }
8576
8677 @ Override
87- void initializeProxy () {
88- super .initializeProxy ();
78+ void initialize () {
79+ super .initialize ();
8980
9081 //Handle legacy USB connections
9182 if (_transportConfig != null && TransportType .USB .equals (_transportConfig .getTransportType ())) {
@@ -113,9 +104,9 @@ void initializeProxy() {
113104 }
114105
115106 @ Override
116- void cycleProxy (SdlDisconnectedReason disconnectedReason ) {
117- cleanProxy ();
118- initializeProxy ();
107+ void cycle (SdlDisconnectedReason disconnectedReason ) {
108+ clean ();
109+ initialize ();
119110 if (!SdlDisconnectedReason .LEGACY_BLUETOOTH_MODE_ENABLED .equals (disconnectedReason ) && !SdlDisconnectedReason .PRIMARY_TRANSPORT_CYCLE_REQUEST .equals (disconnectedReason )) {
120111 //We don't want to alert higher if we are just cycling for legacy bluetooth
121112 onClose ("Sdl Proxy Cycled" , new SdlException ("Sdl Proxy Cycled" , SdlExceptionCause .SDL_PROXY_CYCLED ), disconnectedReason );
@@ -131,14 +122,19 @@ void cycleProxy(SdlDisconnectedReason disconnectedReason) {
131122
132123 @ RestrictTo (RestrictTo .Scope .LIBRARY )
133124 public void setContext (Context context ) {
134- this .context = context ;
125+ this .contextWeakReference = new WeakReference <>( context ) ;
135126 }
136127
137128 @ Override
138129 void setSdlSecurityStaticVars () {
139130 super .setSdlSecurityStaticVars ();
140131
132+ Context context = null ;
141133 Service service = null ;
134+
135+ if (this .contextWeakReference != null ){
136+ context = contextWeakReference .get ();
137+ }
142138 if (context != null && context instanceof Service ) {
143139 service = (Service ) context ;
144140 }
@@ -147,11 +143,11 @@ void setSdlSecurityStaticVars() {
147143 }
148144
149145 @ Override
150- void onProtocolSessionStarted (SessionType sessionType ) {
151- super .onProtocolSessionStarted (sessionType );
146+ void onServiceStarted (SessionType sessionType ) {
147+ super .onServiceStarted (sessionType );
152148 if (sessionType .eq (SessionType .NAV )) {
153- navServiceStartResponseReceived = true ;
154- navServiceStartResponse = true ;
149+ videoServiceStartResponseReceived = true ;
150+ videoServiceStartResponse = true ;
155151 }
156152 }
157153
@@ -161,42 +157,18 @@ void onTransportDisconnected(String info, boolean availablePrimary, BaseTranspor
161157 if (availablePrimary ) {
162158 _transportConfig = transportConfig ;
163159 Log .d (TAG , "notifying RPC session ended, but potential primary transport available" );
164- cycleProxy (SdlDisconnectedReason .PRIMARY_TRANSPORT_CYCLE_REQUEST );
160+ cycle (SdlDisconnectedReason .PRIMARY_TRANSPORT_CYCLE_REQUEST );
165161 } else {
166162 onClose (info , null , null );
167163 }
168164 }
169165
170166 @ Override
171- void onProtocolSessionStartedNACKed (SessionType sessionType ) {
172- super .onProtocolSessionStartedNACKed (sessionType );
173- if (sessionType .eq (SessionType .NAV )) {
174- navServiceStartResponseReceived = true ;
175- navServiceStartResponse = false ;
176- }
177- }
178-
179- @ Override
180- void onProtocolSessionEnded (SessionType sessionType ) {
181- super .onProtocolSessionEnded (sessionType );
167+ void onStartServiceNACKed (SessionType sessionType ) {
168+ super .onStartServiceNACKed (sessionType );
182169 if (sessionType .eq (SessionType .NAV )) {
183- navServiceEndResponseReceived = true ;
184- navServiceEndResponse = true ;
185- } else if (sessionType .eq (SessionType .PCM )) {
186- pcmServiceEndResponseReceived = true ;
187- pcmServiceEndResponse = true ;
188- }
189- }
190-
191- @ Override
192- void onProtocolSessionEndedNACKed (SessionType sessionType ) {
193- super .onProtocolSessionEndedNACKed (sessionType );
194- if (sessionType .eq (SessionType .NAV )) {
195- navServiceEndResponseReceived = true ;
196- navServiceEndResponse = false ;
197- } else if (sessionType .eq (SessionType .PCM )) {
198- pcmServiceEndResponseReceived = true ;
199- pcmServiceEndResponse = false ;
170+ videoServiceStartResponseReceived = true ;
171+ videoServiceStartResponse = false ;
200172 }
201173 }
202174
@@ -233,72 +205,60 @@ void startVideoService(boolean isEncrypted, VideoStreamingParameters parameters)
233205 * mode (i.e. without any negotiation) then an instance of VideoStreamingParams is
234206 * returned. If the service was not opened then null is returned.
235207 */
236- private VideoStreamingParameters tryStartVideoStream (boolean isEncrypted , VideoStreamingParameters parameters ) {
208+ private void tryStartVideoStream (boolean isEncrypted , VideoStreamingParameters parameters ) {
237209 if (session == null ) {
238210 DebugTool .logWarning ("SdlSession is not created yet." );
239- return null ;
211+ return ;
240212 }
241213 if (getProtocolVersion () != null && getProtocolVersion ().getMajor () >= 5 && !systemCapabilityManager .isCapabilitySupported (SystemCapabilityType .VIDEO_STREAMING )) {
242214 DebugTool .logWarning ("Module doesn't support video streaming." );
243- return null ;
215+ return ;
244216 }
245217 if (parameters == null ) {
246218 DebugTool .logWarning ("Video parameters were not supplied." );
247- return null ;
219+ return ;
248220 }
249221
250- if (!navServiceStartResponseReceived || !navServiceStartResponse //If we haven't started the service before
251- || (navServiceStartResponse && isEncrypted && !session .isServiceProtected (SessionType .NAV ))) { //Or the service has been started but we'd like to start an encrypted one
222+
223+ if (!videoServiceStartResponseReceived || !videoServiceStartResponse //If we haven't started the service before
224+ || (videoServiceStartResponse && isEncrypted && !session .isServiceProtected (SessionType .NAV ))) { //Or the service has been started but we'd like to start an encrypted one
252225 session .setDesiredVideoParams (parameters );
253226
254- navServiceStartResponseReceived = false ;
255- navServiceStartResponse = false ;
227+ videoServiceStartResponseReceived = false ;
228+ videoServiceStartResponse = false ;
256229
230+ addVideoServiceListener ();
257231 session .startService (SessionType .NAV , session .getSessionId (), isEncrypted );
258- addNavListener ();
259- FutureTask <Void > fTask = new FutureTask <>(new CallableMethod (RESPONSE_WAIT_TIME ));
260- ScheduledExecutorService scheduler = Executors .newSingleThreadScheduledExecutor ();
261- scheduler .execute (fTask );
262-
263- //noinspection StatementWithEmptyBody
264- while (!navServiceStartResponseReceived && !fTask .isDone ()) ;
265- scheduler .shutdown ();
266- }
267232
268- if (navServiceStartResponse ) {
269- if (getProtocolVersion () != null && getProtocolVersion ().getMajor () < 5 ) { //Versions 1-4 do not support streaming parameter negotiations
270- session .setAcceptedVideoParams (parameters );
271- }
272- return session .getAcceptedVideoParams ();
273233 }
274-
275- return null ;
276234 }
277235
278- private void addNavListener () {
236+ private void addVideoServiceListener () {
279237 // videos may be started and stopped. Only add this once
280- if (navServiceListener == null ) {
238+ if (videoServiceListener == null ) {
281239
282- navServiceListener = new ISdlServiceListener () {
240+ videoServiceListener = new ISdlServiceListener () {
283241 @ Override
284242 public void onServiceStarted (SdlSession session , SessionType type , boolean isEncrypted ) {
243+ videoServiceStartResponseReceived = true ;
244+ videoServiceStartResponse = true ;
285245 }
286246
287247 @ Override
288248 public void onServiceEnded (SdlSession session , SessionType type ) {
289249 // reset nav flags so nav can start upon the next transport connection
290- navServiceStartResponseReceived = false ;
291- navServiceStartResponse = false ;
250+ videoServiceStartResponseReceived = false ;
251+ videoServiceStartResponse = false ;
292252 }
293253
294254 @ Override
295255 public void onServiceError (SdlSession session , SessionType type , String reason ) {
296256 // if there is an error reset the flags so that there is a chance to restart streaming
297- navServiceStartResponseReceived = false ;
298- navServiceStartResponse = false ;
257+ videoServiceStartResponseReceived = false ;
258+ videoServiceStartResponse = false ;
299259 }
300260 };
301- session .addServiceListener (SessionType .NAV , navServiceListener );
261+ session .addServiceListener (SessionType .NAV , videoServiceListener );
302262 }
303263 }
304264
@@ -308,29 +268,17 @@ public void onServiceError(SdlSession session, SessionType type, String reason)
308268 * @return true if the video service is closed successfully, return false otherwise
309269 */
310270 @ Override
311- boolean endVideoStream () {
271+ void endVideoStream () {
312272 if (session == null ) {
313273 DebugTool .logWarning ("SdlSession is not created yet." );
314- return false ;
274+ return ;
315275 }
316276 if (!session .getIsConnected ()) {
317277 DebugTool .logWarning ("Connection is not available." );
318- return false ;
278+ return ;
319279 }
320280
321- navServiceEndResponseReceived = false ;
322- navServiceEndResponse = false ;
323281 session .stopVideoStream ();
324-
325- FutureTask <Void > fTask = new FutureTask <>(new CallableMethod (RESPONSE_WAIT_TIME ));
326- ScheduledExecutorService scheduler = Executors .newSingleThreadScheduledExecutor ();
327- scheduler .execute (fTask );
328-
329- //noinspection StatementWithEmptyBody
330- while (!navServiceEndResponseReceived && !fTask .isDone ()) ;
331- scheduler .shutdown ();
332-
333- return navServiceEndResponse ;
334282 }
335283
336284 @ Override
@@ -352,46 +300,16 @@ void startAudioService(boolean isEncrypted) {
352300 * @return true if the audio service is closed successfully, return false otherwise
353301 */
354302 @ Override
355- boolean endAudioStream () {
303+ void endAudioStream () {
356304 if (session == null ) {
357305 DebugTool .logWarning ("SdlSession is not created yet." );
358- return false ;
306+ return ;
359307 }
360308 if (!session .getIsConnected ()) {
361309 DebugTool .logWarning ("Connection is not available." );
362- return false ;
310+ return ;
363311 }
364312
365- pcmServiceEndResponseReceived = false ;
366- pcmServiceEndResponse = false ;
367313 session .stopAudioStream ();
368-
369- FutureTask <Void > fTask = new FutureTask <>(new CallableMethod (RESPONSE_WAIT_TIME ));
370- ScheduledExecutorService scheduler = Executors .newSingleThreadScheduledExecutor ();
371- scheduler .execute (fTask );
372-
373- //noinspection StatementWithEmptyBody
374- while (!pcmServiceEndResponseReceived && !fTask .isDone ()) ;
375- scheduler .shutdown ();
376-
377- return pcmServiceEndResponse ;
378- }
379-
380- private class CallableMethod implements Callable <Void > {
381- private final long waitTime ;
382-
383- public CallableMethod (int timeInMillis ) {
384- this .waitTime = timeInMillis ;
385- }
386-
387- @ Override
388- public Void call () {
389- try {
390- Thread .sleep (waitTime );
391- } catch (InterruptedException e ) {
392- e .printStackTrace ();
393- }
394- return null ;
395- }
396314 }
397315}
0 commit comments