1 /*
2  * Copyright (C) 2022 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 
17 package android.telephony.ims;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.os.Binder;
23 
24 import com.android.internal.telephony.ISipDialogStateCallback;
25 
26 import java.lang.ref.WeakReference;
27 import java.util.List;
28 import java.util.concurrent.Executor;
29 
30 /**
31  * This callback is used to notify listeners of SIP Dialog state changes.
32  * @hide
33  */
34 @SystemApi
35 public abstract class SipDialogStateCallback {
36 
37     private CallbackBinder mCallback;
38     /**
39     * @hide
40     */
attachExecutor(@onNull @allbackExecutor Executor executor)41     public void attachExecutor(@NonNull @CallbackExecutor Executor executor) {
42         if (executor == null) {
43             throw new IllegalArgumentException("SipDialogStateCallback Executor must be non-null");
44         }
45         mCallback = new CallbackBinder(this, executor);
46     }
47 
48     private static class CallbackBinder extends ISipDialogStateCallback.Stub {
49         private WeakReference<SipDialogStateCallback> mSipDialogStateCallbackWeakRef;
50         private Executor mExecutor;
51 
CallbackBinder(SipDialogStateCallback callback, Executor executor)52         private CallbackBinder(SipDialogStateCallback callback, Executor executor) {
53             mSipDialogStateCallbackWeakRef = new WeakReference<SipDialogStateCallback>(callback);
54             mExecutor = executor;
55         }
56 
getExecutor()57         Executor getExecutor() {
58             return mExecutor;
59         }
60 
61         @Override
onActiveSipDialogsChanged(List<SipDialogState> dialogs)62         public void onActiveSipDialogsChanged(List<SipDialogState> dialogs) {
63             SipDialogStateCallback callback = mSipDialogStateCallbackWeakRef.get();
64             if (callback == null || dialogs == null) return;
65 
66             Binder.withCleanCallingIdentity(
67                     () -> mExecutor.execute(() -> callback.onActiveSipDialogsChanged(dialogs)));
68         }
69     }
70 
71     /**
72      * The state of one or more SIP dialogs has changed.
73      *
74      * @param dialogs A List of SipDialogState objects representing the state of the active
75      *               SIP Dialogs.
76      */
onActiveSipDialogsChanged(@onNull List<SipDialogState> dialogs)77     public abstract void onActiveSipDialogsChanged(@NonNull List<SipDialogState> dialogs);
78 
79     /**
80      * An unexpected error has occurred and the Telephony process has crashed. This
81      * has caused this callback to be deregistered. The callback must be re-registered
82      * in order to continue listening to the IMS service state.
83      */
onError()84     public abstract void onError();
85 
86     /**
87      * The callback to notify the death of telephony process
88      * @hide
89      */
binderDied()90     public final void binderDied() {
91         if (mCallback != null) {
92             mCallback.getExecutor().execute(() -> onError());
93         }
94     }
95 
96     /**
97      * Return the callback binder
98      * @hide
99      */
getCallbackBinder()100     public CallbackBinder getCallbackBinder() {
101         return mCallback;
102     }
103 }
104