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