1/*
2 * Copyright (C) 2016 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
17package com.android.server.wifi;
18
19import android.os.IBinder;
20import android.os.IBinder.DeathRecipient;
21import android.os.RemoteException;
22import com.android.internal.util.StateMachine;
23
24/**
25 * Allows StateMachine instances to subscribe to binder death.
26 *
27 * @hide
28 */
29public class StateMachineDeathRecipient implements DeathRecipient {
30
31    private final StateMachine mStateMachine;
32    private final int mDeathCommand;
33    private IBinder mLinkedBinder;
34
35    /**
36     * Construct a StateMachineDeathRecipient.
37     *
38     * @param sm StateMachine instance to receive a message upon Binder death.
39     * @param command message to send the state machine.
40     */
41    public StateMachineDeathRecipient(StateMachine sm, int command) {
42        mStateMachine = sm;
43        mDeathCommand = command;
44    }
45
46    /**
47     * Listen for the death of a binder.
48     *
49     * This method will unlink from death notifications from any
50     * previously linked IBinder instance.
51     *
52     * @param binder remote object to listen for death.
53     * @return true iff we have successfully subscribed to death notifications of a live
54     *         IBinder instance.
55     */
56    public boolean linkToDeath(IBinder binder) {
57        unlinkToDeath();
58        try {
59            binder.linkToDeath(this, 0);
60        } catch (RemoteException e) {
61            // The remote has already died.
62            return false;
63        }
64        mLinkedBinder = binder;
65        return true;
66    }
67
68    /**
69     * Unlink from notifications from the last linked IBinder instance.
70     */
71    public void unlinkToDeath() {
72        if (mLinkedBinder == null) {
73            return;
74        }
75        mLinkedBinder.unlinkToDeath(this, 0);
76        mLinkedBinder = null;
77    }
78
79    /**
80     * Called by the binder subsystem upon remote object death.
81     */
82    @Override
83    public void binderDied() {
84        mStateMachine.sendMessage(mDeathCommand);
85    }
86}