content: /*
   * Copyright (C) 2017 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.internal.telephony;
  
  import android.app.ActivityManager;
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.os.UserHandle;
  import android.util.Log;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  /**
   * This class is used to broadcast intents that need to be rebroadcast after the device is unlocked.
   * NOTE: Currently this is used only for SIM_STATE_CHANGED so logic is hardcoded for that;
   * for example broadcasts are always sticky, only the last intent for the slotId is rebroadcast,
   * etc.
   */
  public class IntentBroadcaster {
      private static final String TAG = "IntentBroadcaster";
  
      private Map<Integer, Intent> mRebroadcastIntents = new HashMap<>();
      private static IntentBroadcaster sIntentBroadcaster;
  
      private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              String action = intent.getAction();
              if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
                  synchronized (mRebroadcastIntents) {
                      // rebroadcast intents
                      Iterator iterator = mRebroadcastIntents.entrySet().iterator();
                      while (iterator.hasNext()) {
                          Map.Entry pair = (Map.Entry) iterator.next();
                          Intent i = (Intent) pair.getValue();
                          i.putExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, true);
                          iterator.remove();
                          logd("Rebroadcasting intent " + i.getAction() + " "
                                  + i.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
                                  + " for slotId " + pair.getKey());
                          ActivityManager.broadcastStickyIntent(i, UserHandle.USER_ALL);
                      }
                  }
              }
          }
      };
  
      private IntentBroadcaster(Context context) {
          context.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
      }
  
      /**
       * Method to get an instance of IntentBroadcaster after creating one if needed.
       * @return IntentBroadcaster instance
       */
      public static IntentBroadcaster getInstance(Context context) {
          if (sIntentBroadcaster == null) {
              sIntentBroadcaster = new IntentBroadcaster(context);
          }
          return sIntentBroadcaster;
      }
  
      public static IntentBroadcaster getInstance() {
          return sIntentBroadcaster;
      }
  
      /**
       * Wrapper for ActivityManager.broadcastStickyIntent() that also stores intent to be rebroadcast
       * on USER_UNLOCKED
       */
      public void broadcastStickyIntent(Intent intent, int slotId) {
          logd("Broadcasting and adding intent for rebroadcast: " + intent.getAction() + " "
                  + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
                  + " for slotId " + slotId);
          synchronized (mRebroadcastIntents) {
              ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
              mRebroadcastIntents.put(slotId, intent);
          }
      }
  
      private void logd(String s) {
          Log.d(TAG, s);
      }
  }
  