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