1 /*
2  * Copyright (C) 2017 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.telephony;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.UserHandle;
24 import android.util.Log;
25 
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 
30 /**
31  * This class is used to broadcast intents that need to be rebroadcast after the device is unlocked.
32  * NOTE: Currently this is used only for SIM_STATE_CHANGED so logic is hardcoded for that;
33  * for example broadcasts are always sticky, only the last intent for the slotId is rebroadcast,
34  * etc.
35  */
36 public class IntentBroadcaster {
37     private static final String TAG = "IntentBroadcaster";
38 
39     private Map<Integer, Intent> mRebroadcastIntents = new HashMap<>();
40     private static IntentBroadcaster sIntentBroadcaster;
41 
42     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
43         @Override
44         public void onReceive(Context context, Intent intent) {
45             String action = intent.getAction();
46             if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
47                 synchronized (mRebroadcastIntents) {
48                     // rebroadcast intents
49                     Iterator iterator = mRebroadcastIntents.entrySet().iterator();
50                     while (iterator.hasNext()) {
51                         Map.Entry pair = (Map.Entry) iterator.next();
52                         Intent i = (Intent) pair.getValue();
53                         i.putExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, true);
54                         iterator.remove();
55                         logd("Rebroadcasting intent " + i.getAction() + " "
56                                 + i.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
57                                 + " for slotId " + pair.getKey());
58                         context.sendStickyBroadcastAsUser(i, UserHandle.ALL);
59                     }
60                 }
61             }
62         }
63     };
64 
IntentBroadcaster(Context context)65     private IntentBroadcaster(Context context) {
66         context.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
67     }
68 
69     /**
70      * Method to get an instance of IntentBroadcaster after creating one if needed.
71      * @return IntentBroadcaster instance
72      */
getInstance(Context context)73     public static IntentBroadcaster getInstance(Context context) {
74         if (sIntentBroadcaster == null) {
75             sIntentBroadcaster = new IntentBroadcaster(context);
76         }
77         return sIntentBroadcaster;
78     }
79 
getInstance()80     public static IntentBroadcaster getInstance() {
81         return sIntentBroadcaster;
82     }
83 
84     /**
85      * Wrapper for ActivityManager.broadcastStickyIntent() that also stores intent to be rebroadcast
86      * on USER_UNLOCKED
87      */
broadcastStickyIntent(Context context, Intent intent, int phoneId)88     public void broadcastStickyIntent(Context context, Intent intent, int phoneId) {
89         logd("Broadcasting and adding intent for rebroadcast: " + intent.getAction() + " "
90                 + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
91                 + " for phoneId " + phoneId);
92         synchronized (mRebroadcastIntents) {
93             context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
94             mRebroadcastIntents.put(phoneId, intent);
95         }
96     }
97 
logd(String s)98     private void logd(String s) {
99         Log.d(TAG, s);
100     }
101 }
102