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