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 com.android.server.wm;
18 
19 import android.content.Context;
20 import android.os.IBinder;
21 import android.os.RemoteException;
22 import android.window.ITaskFpsCallback;
23 
24 import java.util.HashMap;
25 
26 final class TaskFpsCallbackController {
27 
28     private final Context mContext;
29     private final HashMap<IBinder, Long> mTaskFpsCallbacks;
30     private final HashMap<IBinder, IBinder.DeathRecipient> mDeathRecipients;
31 
TaskFpsCallbackController(Context context)32     TaskFpsCallbackController(Context context) {
33         mContext = context;
34         mTaskFpsCallbacks = new HashMap<>();
35         mDeathRecipients = new HashMap<>();
36     }
37 
registerListener(int taskId, ITaskFpsCallback callback)38     void registerListener(int taskId, ITaskFpsCallback callback) {
39         if (callback == null) {
40             return;
41         }
42 
43         IBinder binder = callback.asBinder();
44         if (mTaskFpsCallbacks.containsKey(binder)) {
45             return;
46         }
47 
48         final long nativeListener = nativeRegister(callback, taskId);
49         mTaskFpsCallbacks.put(binder, nativeListener);
50 
51         final IBinder.DeathRecipient deathRecipient = () -> unregisterListener(callback);
52         try {
53             binder.linkToDeath(deathRecipient, 0);
54             mDeathRecipients.put(binder, deathRecipient);
55         } catch (RemoteException e) {
56             // ignore
57         }
58     }
59 
unregisterListener(ITaskFpsCallback callback)60     void unregisterListener(ITaskFpsCallback callback) {
61         if (callback == null) {
62             return;
63         }
64 
65         IBinder binder = callback.asBinder();
66         if (!mTaskFpsCallbacks.containsKey(binder)) {
67             return;
68         }
69 
70         binder.unlinkToDeath(mDeathRecipients.get(binder), 0);
71         mDeathRecipients.remove(binder);
72 
73         nativeUnregister(mTaskFpsCallbacks.get(binder));
74         mTaskFpsCallbacks.remove(binder);
75     }
76 
nativeRegister(ITaskFpsCallback callback, int taskId)77     private static native long nativeRegister(ITaskFpsCallback callback, int taskId);
nativeUnregister(long ptr)78     private static native void nativeUnregister(long ptr);
79 }
80