1 /*
2  * Copyright (C) 2020 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.internal.net.ipsec.ike.utils;
18 
19 import static android.net.ipsec.ike.IkeManager.getIkeLog;
20 
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.util.SparseArray;
27 
28 import java.util.HashSet;
29 
30 /**
31  * IkeAlarmReceiver represents a class that receives all the alarms set by IKE library
32  *
33  * <p>Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is
34  * executing. Once onReceive() returns, the Alarm Manager releases this wake lock. Thus actions that
35  * contain asynchronous process to complete might need acquire a wake lock later.
36  */
37 public class IkeAlarmReceiver extends BroadcastReceiver {
38     // Broadcast intent actions when an IKE Session event alarm is fired
39     public static final String ACTION_DELETE_CHILD = "IkeAlarmReceiver.ACTION_DELETE_CHILD";
40     public static final String ACTION_REKEY_CHILD = "IkeAlarmReceiver.ACTION_REKEY_CHILD";
41     public static final String ACTION_DELETE_IKE = "IkeAlarmReceiver.ACTION_DELETE_IKE";
42     public static final String ACTION_REKEY_IKE = "IkeAlarmReceiver.ACTION_REKEY_IKE";
43     public static final String ACTION_DPD = "IkeAlarmReceiver.ACTION_DPD";
44     public static final String ACTION_KEEPALIVE = "IkeAlarmReceiver.ACTION_KEEPALIVE";
45 
46     private static final HashSet<String> sIkeSessionActionsSet = new HashSet<>();
47 
48     static {
49         sIkeSessionActionsSet.add(ACTION_DELETE_CHILD);
50         sIkeSessionActionsSet.add(ACTION_REKEY_CHILD);
51         sIkeSessionActionsSet.add(ACTION_DELETE_IKE);
52         sIkeSessionActionsSet.add(ACTION_REKEY_IKE);
53         sIkeSessionActionsSet.add(ACTION_DPD);
54     }
55 
56     /** Parcelable name of Message that is owned by IKE Session StateMachine */
57     public static final String PARCELABLE_NAME_IKE_SESSION_MSG =
58             "IkeAlarmReceiver.PARCELABLE_NAME_IKE_SESSION_MSG";
59 
60     private final SparseArray<Handler> mIkeSessionIdToHandlerMap = new SparseArray<>();
61 
62     /**
63      * Called when an alarm fires.
64      *
65      * <p>This is method is guaranteed to run on IkeSessionStateMachine thread since
66      * IkeAlarmReceiver is registered with IkeSessionStateMachine Handler
67      */
68     @Override
onReceive(Context context, Intent intent)69     public void onReceive(Context context, Intent intent) {
70         final String action = intent.getAction();
71         getIkeLog()
72                 .d(
73                         "IkeAlarmReceiver",
74                         "Alarm fired: action " + action + " id " + intent.getIdentifier());
75         switch (action) {
76             case ACTION_DELETE_CHILD: // fallthrough
77             case ACTION_REKEY_CHILD: // fallthrough
78             case ACTION_DELETE_IKE: // fallthrough
79             case ACTION_REKEY_IKE: // fallthrough
80             case ACTION_DPD: // fallthrough
81             case ACTION_KEEPALIVE:
82                 // This Message has lost its target information after being sent as a Broadcast
83                 Message message =
84                         (Message) intent.getExtras().getParcelable(PARCELABLE_NAME_IKE_SESSION_MSG);
85                 Handler ikeHandler = mIkeSessionIdToHandlerMap.get(message.arg1);
86 
87                 if (ikeHandler != null) {
88                     // Use #dispatchMessage so that this method won't return until the message is
89                     // processed
90                     ikeHandler.dispatchMessage(message);
91                 }
92                 return;
93             default:
94                 getIkeLog().d("IkeAlarmReceiver", "Received unrecognized alarm intent");
95         }
96     }
97 
98     /** Register a newly created IkeSessionStateMachine handler */
registerIkeSession(int ikeSessionId, Handler ikeSesisonHandler)99     public void registerIkeSession(int ikeSessionId, Handler ikeSesisonHandler) {
100         mIkeSessionIdToHandlerMap.put(ikeSessionId, ikeSesisonHandler);
101     }
102 
103     /** Unregistered the deleted IkeSessionStateMachine */
unregisterIkeSession(int ikeSessionId)104     public void unregisterIkeSession(int ikeSessionId) {
105         mIkeSessionIdToHandlerMap.remove(ikeSessionId);
106     }
107 }
108