private boolean showCallScreenInternal(
     boolean specifyInitialDialpadState, boolean initialDialpadState) {
   if (!PhoneApp.sVoiceCapable) {
     // Never allow the InCallScreen to appear on data-only devices.
     return false;
   }
   if (isIdle()) {
     return false;
   }
   // If the phone isn't idle then go to the in-call screen
   long callingId = Binder.clearCallingIdentity();
   try {
     Intent intent;
     if (specifyInitialDialpadState) {
       intent = PhoneApp.createInCallIntent(initialDialpadState);
     } else {
       intent = PhoneApp.createInCallIntent();
     }
     try {
       mApp.mContext.startActivity(intent);
     } catch (ActivityNotFoundException e) {
       // It's possible that the in-call UI might not exist
       // (like on non-voice-capable devices), although we
       // shouldn't be trying to bring up the InCallScreen on
       // devices like that in the first place!
       Log.w(
           LOG_TAG,
           "showCallScreenInternal: " + "transition to InCallScreen failed; intent = " + intent);
     }
   } finally {
     Binder.restoreCallingIdentity(callingId);
   }
   return true;
 }
  /**
   * cleanup any undismissed ota dialogs so the InCallScreen UI can be shown
   *
   * @return void
   */
  private void otaCleanup() {

    PhoneApp app = PhoneApp.getInstance();
    boolean isOtaCallActive = false;

    if (TelephonyCapabilities.supportsOtasp(app.phone)) {
      boolean activateState =
          (app.cdmaOtaScreenState.otaScreenState
              == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION);
      boolean dialogState =
          (app.cdmaOtaScreenState.otaScreenState
              == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG);

      if (activateState || dialogState) {
        // The OTASP sequence is active, but either (1) the call
        // hasn't started yet, or (2) the call has ended and we're
        // showing the success/failure screen. In either of these
        // cases it's OK to make a new outgoing call, but we need
        // to take down any OTASP-related UI first.
        if (dialogState) app.dismissOtaDialogs();
        app.clearOtaState();
        app.clearInCallScreenMode();
      }
    }
  }
    /**
     * Handles the user canceling the popup, either by touching outside the popup or by pressing
     * Back.
     */
    @Override
    public void onCancel(DialogInterface dialog) {
      if (DBG) log("RespondViaSmsCancelListener.onCancel()...");

      dismissPopup();

      final PhoneConstants.State state = PhoneApp.getInstance().mCM.getState();
      if (state == PhoneConstants.State.IDLE) {
        // This means the incoming call is already hung up when the user chooses not to
        // use "Respond via SMS" feature. Let's just exit the whole in-call screen.
        PhoneApp.getInstance().dismissCallScreen();
      } else {

        // If the user cancels the popup, this presumably means that
        // they didn't actually mean to bring up the "Respond via SMS"
        // UI in the first place (and instead want to go back to the
        // state where they can either answer or reject the call.)
        // So restart the ringer and bring back the regular incoming
        // call UI.

        // This will have no effect if the incoming call isn't still ringing.
        PhoneApp.getInstance().notifier.restartRinger();

        // We hid the GlowPadView widget way back in
        // InCallTouchUi.onTrigger(), when the user first selected
        // the "SMS" trigger.
        //
        // To bring it back, just force the entire InCallScreen to
        // update itself based on the current telephony state.
        // (Assuming the incoming call is still ringing, this will
        // cause the incoming call widget to reappear.)
        mInCallScreen.requestUpdateScreen();
      }
    }
    /** Handles the user selecting an item from the popup. */
    @Override
    public void onItemClick(
        AdapterView<?> parent, // The ListView
        View view, // The TextView that was clicked
        int position,
        long id) {
      if (DBG) log("RespondViaSmsItemClickListener.onItemClick(" + position + ")...");
      String message = (String) parent.getItemAtPosition(position);
      if (VDBG) log("- message: '" + message + "'");

      // The "Custom" choice is a special case.
      // (For now, it's guaranteed to be the last item.)
      if (position == (parent.getCount() - 1)) {
        // Take the user to the standard SMS compose UI.
        launchSmsCompose(mPhoneNumber);
      } else {
        // Send the selected message immediately with no user interaction.
        sendText(mPhoneNumber, message);

        // ...and show a brief confirmation to the user (since
        // otherwise it's hard to be sure that anything actually
        // happened.)
        final Resources res = mInCallScreen.getResources();
        String formatString = res.getString(R.string.respond_via_sms_confirmation_format);
        String confirmationMsg = String.format(formatString, mPhoneNumber);
        Toast.makeText(mInCallScreen, confirmationMsg, Toast.LENGTH_LONG).show();

        // TODO: If the device is locked, this toast won't actually ever
        // be visible!  (That's because we're about to dismiss the call
        // screen, which means that the device will return to the
        // keyguard.  But toasts aren't visible on top of the keyguard.)
        // Possible fixes:
        // (1) Is it possible to allow a specific Toast to be visible
        //     on top of the keyguard?
        // (2) Artifically delay the dismissCallScreen() call by 3
        //     seconds to allow the toast to be seen?
        // (3) Don't use a toast at all; instead use a transient state
        //     of the InCallScreen (perhaps via the InCallUiState
        //     progressIndication feature), and have that state be
        //     visible for 3 seconds before calling dismissCallScreen().
      }

      // At this point the user is done dealing with the incoming call, so
      // there's no reason to keep it around.  (It's also confusing for
      // the "incoming call" icon in the status bar to still be visible.)
      // So reject the call now.
      mInCallScreen.hangupRingingCall();

      dismissPopup();

      final PhoneConstants.State state = PhoneApp.getInstance().mCM.getState();
      if (state == PhoneConstants.State.IDLE) {
        // There's no other phone call to interact. Exit the entire in-call screen.
        PhoneApp.getInstance().dismissCallScreen();
      } else {
        // The user is still in the middle of other phone calls, so we should keep the
        // in-call screen.
        mInCallScreen.requestUpdateScreen();
      }
    }
 /** Private constructor; @see init() */
 private PhoneInterfaceManager(PhoneApp app, Phone phone) {
   mApp = app;
   mPhone = phone;
   mCM = PhoneApp.getInstance().mCM;
   mMainThreadHandler = new MainThreadHandler();
   Log.d(LOG_TAG, " Registering for UNSOL OEM HOOK Responses to deliver external apps");
   mPhone.setOnUnsolOemHookExtApp(mMainThreadHandler, EVENT_UNSOL_OEM_HOOK_EXT_APP, null);
   publish();
 }
  @Override
  public void onCreate() {
    super.onCreate();
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    mBtHandsfree = PhoneApp.getInstance().getBluetoothHandsfree();
    mAg = new BluetoothAudioGateway(mAdapter);
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
    filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
    filter.addAction(BluetoothDevice.ACTION_UUID);
    registerReceiver(mBluetoothReceiver, filter);

    IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
    if (b == null) {
      throw new RuntimeException("Bluetooth service not available");
    }
    mBluetoothService = IBluetooth.Stub.asInterface(b);
    mRemoteHeadsets = new HashMap<BluetoothDevice, BluetoothRemoteHeadset>();
  }
示例#7
0
    /**
     * Handles the user canceling the popup, either by touching outside the popup or by pressing
     * Back.
     */
    public void onCancel(DialogInterface dialog) {
      if (DBG) log("RespondViaSmsCancelListener.onCancel()...");

      // If the user cancels the popup, this presumably means that
      // they didn't actually mean to bring up the "Respond via SMS"
      // UI in the first place (and instead want to go back to the
      // state where they can either answer or reject the call.)
      // So restart the ringer and bring back the regular incoming
      // call UI.

      // This will have no effect if the incoming call isn't still ringing.
      PhoneApp.getInstance().notifier.restartRinger();

      // We hid the MultiWaveView widget way back in
      // InCallTouchUi.onTrigger(), when the user first selected
      // the "SMS" trigger.
      //
      // To bring it back, just force the entire InCallScreen to
      // update itself based on the current telephony state.
      // (Assuming the incoming call is still ringing, this will
      // cause the incoming call widget to reappear.)
      mInCallScreen.requestUpdateScreen();
    }
  /**
   * Check if ota call is active
   *
   * @return True if ota call is still active False if ota call is not active
   */
  private boolean isOtaActive() {

    PhoneApp app = PhoneApp.getInstance();
    boolean isOtaCallActive = false;

    if (TelephonyCapabilities.supportsOtasp(app.phone)) {

      // TODO: Need cleaner way to check if OTA is active.
      // Also, this check seems to be broken in one obscure case: if
      // you interrupt an OTASP call by pressing Back then Skip,
      // otaScreenState somehow gets left in either PROGRESS or
      // LISTENING.
      if ((app.cdmaOtaScreenState.otaScreenState
              == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS)
          || (app.cdmaOtaScreenState.otaScreenState
              == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING)) {
        isOtaCallActive = true;
        // The actual OTASP call is active. Don't allow new
        // outgoing calls at all from this state.
        Log.w(TAG, "OTASP call is active");
      }
    }
    return isOtaCallActive;
  }
  private void processIntent(Intent intent) {
    String action = intent.getAction();
    intent.putExtra(SUBSCRIPTION_KEY, mSubscription);
    Log.d(TAG, "outGoingcallBroadCaster action is" + action);
    String number = PhoneNumberUtils.getNumberFromIntent(intent, this);
    Log.d(TAG, " number from Intent : " + number);
    // Check the number, don't convert for sip uri
    // TODO put uriNumber under PhoneNumberUtils
    if (number != null) {
      if (!PhoneNumberUtils.isUriNumber(number)) {
        number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
        number = PhoneNumberUtils.stripSeparators(number);
      }
    }

    // If true, this flag will indicate that the current call is a special kind
    // of call (most likely an emergency number) that 3rd parties aren't allowed
    // to intercept or affect in any way.  (In that case, we start the call
    // immediately rather than going through the NEW_OUTGOING_CALL sequence.)
    boolean callNow;

    if (getClass().getName().equals(intent.getComponent().getClassName())) {
      // If we were launched directly from the OutgoingCallBroadcaster,
      // not one of its more privileged aliases, then make sure that
      // only the non-privileged actions are allowed.
      if (!Intent.ACTION_CALL.equals(intent.getAction())) {
        Log.w(TAG, "Attempt to deliver non-CALL action; forcing to CALL");
        intent.setAction(Intent.ACTION_CALL);
      }
    }

    // Check whether or not this is an emergency number, in order to
    // enforce the restriction that only the CALL_PRIVILEGED and
    // CALL_EMERGENCY intents are allowed to make emergency calls.
    //
    // (Note that the ACTION_CALL check below depends on the result of
    // isPotentialLocalEmergencyNumber() rather than just plain
    // isLocalEmergencyNumber(), to be 100% certain that we *don't*
    // allow 3rd party apps to make emergency calls by passing in an
    // "invalid" number like "9111234" that isn't technically an
    // emergency number but might still result in an emergency call
    // with some networks.)
    final boolean isExactEmergencyNumber =
        (number != null) && PhoneNumberUtils.isLocalEmergencyNumber(number, this);
    final boolean isPotentialEmergencyNumber =
        (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, this);
    if (VDBG) {
      Log.v(TAG, "- Checking restrictions for number '" + number + "':");
      Log.v(TAG, "    isExactEmergencyNumber     = " + isExactEmergencyNumber);
      Log.v(TAG, "    isPotentialEmergencyNumber = " + isPotentialEmergencyNumber);
    }

    /* Change CALL_PRIVILEGED into CALL or CALL_EMERGENCY as needed. */
    // TODO: This code is redundant with some code in InCallScreen: refactor.
    if (Intent.ACTION_CALL_PRIVILEGED.equals(action)) {
      // We're handling a CALL_PRIVILEGED intent, so we know this request came
      // from a trusted source (like the built-in dialer.)  So even a number
      // that's *potentially* an emergency number can safely be promoted to
      // CALL_EMERGENCY (since we *should* allow you to dial "91112345" from
      // the dialer if you really want to.)
      action = isPotentialEmergencyNumber ? Intent.ACTION_CALL_EMERGENCY : Intent.ACTION_CALL;
      if (DBG) Log.v(TAG, "- updating action from CALL_PRIVILEGED to " + action);
      intent.setAction(action);
    }

    if (Intent.ACTION_CALL.equals(action)) {
      if (isPotentialEmergencyNumber) {
        Log.w(
            TAG,
            "Cannot call potential emergency number '"
                + number
                + "' with CALL Intent "
                + intent
                + ".");
        Log.i(TAG, "Launching default dialer instead...");

        Intent invokeFrameworkDialer = new Intent();

        // TwelveKeyDialer is in a tab so we really want
        // DialtactsActivity.  Build the intent 'manually' to
        // use the java resolver to find the dialer class (as
        // opposed to a Context which look up known android
        // packages only)
        invokeFrameworkDialer.setClassName(
            "com.android.contacts", "com.android.contacts.DialtactsActivity");
        invokeFrameworkDialer.setAction(Intent.ACTION_DIAL);
        invokeFrameworkDialer.setData(intent.getData());
        invokeFrameworkDialer.putExtra(SUBSCRIPTION_KEY, mSubscription);

        if (DBG)
          Log.v(TAG, "onCreate(): calling startActivity for Dialer: " + invokeFrameworkDialer);
        startActivity(invokeFrameworkDialer);
        finish();
        return;
      }
      intent.putExtra(SUBSCRIPTION_KEY, mSubscription);
      Log.d(TAG, "for non emergency call,sub is  :" + mSubscription);
      callNow = false;
    } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
      // ACTION_CALL_EMERGENCY case: this is either a CALL_PRIVILEGED
      // intent that we just turned into a CALL_EMERGENCY intent (see
      // above), or else it really is an CALL_EMERGENCY intent that
      // came directly from some other app (e.g. the EmergencyDialer
      // activity built in to the Phone app.)
      // Make sure it's at least *possible* that this is really an
      // emergency number.
      if (!isPotentialEmergencyNumber) {
        Log.w(
            TAG,
            "Cannot call non-potential-emergency number "
                + number
                + " with EMERGENCY_CALL Intent "
                + intent
                + ".");
        finish();
        return;
      }
      int sub = PhoneApp.getInstance().getVoiceSubscriptionInService();
      intent.putExtra(SUBSCRIPTION_KEY, sub);
      Log.d(TAG, "Attempting emergency call on sub :" + sub);
      callNow = true;
    } else {
      Log.e(TAG, "Unhandled Intent " + intent + ".");
      finish();
      return;
    }

    // Make sure the screen is turned on.  This is probably the right
    // thing to do, and more importantly it works around an issue in the
    // activity manager where we will not launch activities consistently
    // when the screen is off (since it is trying to keep them paused
    // and has...  issues).
    //
    // Also, this ensures the device stays awake while doing the following
    // broadcast; technically we should be holding a wake lock here
    // as well.
    PhoneApp.getInstance().wakeUpScreen();

    /* If number is null, we're probably trying to call a non-existent voicemail number,
     * send an empty flash or something else is fishy.  Whatever the problem, there's no
     * number, so there's no point in allowing apps to modify the number. */
    if (number == null || TextUtils.isEmpty(number)) {
      if (intent.getBooleanExtra(EXTRA_SEND_EMPTY_FLASH, false)) {
        Log.i(TAG, "onCreate: SEND_EMPTY_FLASH...");
        PhoneUtils.sendEmptyFlash(PhoneApp.getInstance().getPhone());
        finish();
        return;
      } else {
        Log.i(TAG, "onCreate: null or empty number, setting callNow=true...");
        callNow = true;
        intent.putExtra(SUBSCRIPTION_KEY, mSubscription);
      }
    }

    if (callNow) {
      // This is a special kind of call (most likely an emergency number)
      // that 3rd parties aren't allowed to intercept or affect in any way.
      // So initiate the outgoing call immediately.

      if (DBG) Log.v(TAG, "onCreate(): callNow case! Calling placeCall(): " + intent);

      // Initiate the outgoing call, and simultaneously launch the
      // InCallScreen to display the in-call UI:
      PhoneApp.getInstance().callController.placeCall(intent);

      // Note we do *not* "return" here, but instead continue and
      // send the ACTION_NEW_OUTGOING_CALL broadcast like for any
      // other outgoing call.  (But when the broadcast finally
      // reaches the OutgoingCallReceiver, we'll know not to
      // initiate the call again because of the presence of the
      // EXTRA_ALREADY_CALLED extra.)
    }

    // For now, SIP calls will be processed directly without a
    // NEW_OUTGOING_CALL broadcast.
    //
    // TODO: In the future, though, 3rd party apps *should* be allowed to
    // intercept outgoing calls to SIP addresses as well.  To do this, we should
    // (1) update the NEW_OUTGOING_CALL intent documentation to explain this
    // case, and (2) pass the outgoing SIP address by *not* overloading the
    // EXTRA_PHONE_NUMBER extra, but instead using a new separate extra to hold
    // the outgoing SIP address.  (Be sure to document whether it's a URI or just
    // a plain address, whether it could be a tel: URI, etc.)
    Uri uri = intent.getData();
    String scheme = uri.getScheme();
    if (Constants.SCHEME_SIP.equals(scheme) || PhoneNumberUtils.isUriNumber(number)) {
      startSipCallOptionHandler(this, intent, uri, number);
      finish();
      return;

      // TODO: if there's ever a way for SIP calls to trigger a
      // "callNow=true" case (see above), we'll need to handle that
      // case here too (most likely by just doing nothing at all.)
    }

    final String callOrigin = intent.getStringExtra(PhoneApp.EXTRA_CALL_ORIGIN);
    if (callOrigin != null) {
      if (DBG) Log.v(TAG, "Call origin is passed (" + callOrigin + ")");
      PhoneApp.getInstance().setLatestActiveCallOrigin(callOrigin);
    } else {
      if (DBG) Log.v(TAG, "Call origin is not passed. Reset current one.");
      PhoneApp.getInstance().setLatestActiveCallOrigin(null);
    }

    Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
    if (number != null) {
      broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
    }
    PhoneUtils.checkAndCopyPhoneProviderExtras(intent, broadcastIntent);
    broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow);
    broadcastIntent.putExtra(EXTRA_ORIGINAL_URI, uri.toString());
    broadcastIntent.putExtra(SUBSCRIPTION_KEY, mSubscription);

    if (DBG) Log.v(TAG, "Broadcasting intent: " + broadcastIntent + ".");
    sendOrderedBroadcast(
        broadcastIntent,
        PERMISSION,
        new OutgoingCallReceiver(),
        null, // scheduler
        Activity.RESULT_OK, // initialCode
        number, // initialData: initial value for the result data
        null); // initialExtras
  }
  @Override
  protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    // This method is the single point of entry for the CALL intent,
    // which is used (by built-in apps like Contacts / Dialer, as well
    // as 3rd-party apps) to initiate an outgoing voice call.
    //
    // We also handle two related intents which are only used internally:
    // CALL_PRIVILEGED (which can come from built-in apps like contacts /
    // voice dialer / bluetooth), and CALL_EMERGENCY (from the
    // EmergencyDialer that's reachable from the lockscreen.)
    //
    // The exact behavior depends on the intent's data:
    //
    // - The most typical is a tel: URI, which we handle by starting the
    //   NEW_OUTGOING_CALL broadcast.  That broadcast eventually triggeres
    //   the sequence OutgoingCallReceiver -> SipCallOptionHandler ->
    //   InCallScreen.
    //
    // - Or, with a sip: URI we skip the NEW_OUTGOING_CALL broadcast and
    //   go directly to SipCallOptionHandler, which then leads to the
    //   InCallScreen.
    //
    // - voicemail: URIs take the same path as regular tel: URIs.
    //
    // Other special cases:
    //
    // - Outgoing calls are totally disallowed on non-voice-capable
    //   devices (see handleNonVoiceCapable()).
    //
    // - A CALL intent with the EXTRA_SEND_EMPTY_FLASH extra (and
    //   presumably no data at all) means "send an empty flash" (which
    //   is only meaningful on CDMA devices while a call is already
    //   active.)

    Intent intent = getIntent();
    final Configuration configuration = getResources().getConfiguration();

    if (DBG) Log.v(TAG, "onCreate: this = " + this + ", icicle = " + icicle);
    if (DBG) Log.v(TAG, " - getIntent() = " + intent);
    if (DBG) Log.v(TAG, " - configuration = " + configuration);

    if (icicle != null) {
      // A non-null icicle means that this activity is being
      // re-initialized after previously being shut down.
      //
      // In practice this happens very rarely (because the lifetime
      // of this activity is so short!), but it *can* happen if the
      // framework detects a configuration change at exactly the
      // right moment; see bug 2202413.
      //
      // In this case, do nothing.  Our onCreate() method has already
      // run once (with icicle==null the first time), which means
      // that the NEW_OUTGOING_CALL broadcast for this new call has
      // already been sent.
      Log.i(
          TAG,
          "onCreate: non-null icicle!  "
              + "Bailing out, not sending NEW_OUTGOING_CALL broadcast...");

      // No need to finish() here, since the OutgoingCallReceiver from
      // our original instance will do that.  (It'll actually call
      // finish() on our original instance, which apparently works fine
      // even though the ActivityManager has already shut that instance
      // down.  And note that if we *do* call finish() here, that just
      // results in an "ActivityManager: Duplicate finish request"
      // warning when the OutgoingCallReceiver runs.)

      return;
    }

    // Outgoing phone calls are only allowed on "voice-capable" devices.
    if (!PhoneApp.sVoiceCapable) {
      handleNonVoiceCapable(intent);
      // No need to finish() here; handleNonVoiceCapable() will do
      // that if necessary.
      return;
    }

    /*
     * Clean up any undismissed ota dialogs. If ota call is active outgoing
     * calls will be blocked in OutgoingCallReceiver
     */
    otaCleanup();

    boolean promptEnabled = MSimPhoneFactory.isPromptEnabled();
    String number = PhoneNumberUtils.getNumberFromIntent(intent, this);
    if (TelephonyManager.getDefault().isMultiSimEnabled()
        && promptEnabled
        && (activeSubCount() > 1)
        && (!isIntentFromBluetooth(intent))
        && (!isSIPCall(number, intent))) {
      Log.d(TAG, "Start multisimdialer activity and get the sub selected by user");
      Intent intentMSim = new Intent(this, MSimDialerActivity.class);
      intentMSim.setData(intent.getData());
      intentMSim.setAction(intent.getAction());
      int requestCode = 1;
      startActivityForResult(intentMSim, requestCode);
    } else {
      mSubscription =
          intent.getIntExtra(SUBSCRIPTION_KEY, PhoneApp.getInstance().getVoiceSubscription());
      Log.d(TAG, "subscription when there is (from Extra):" + mSubscription);
      processIntent(intent);
    }
  }
    public void doReceive(Context context, Intent intent) {
      if (DBG) Log.v(TAG, "doReceive: " + intent);

      boolean alreadyCalled;
      String number;
      String originalUri;

      alreadyCalled = intent.getBooleanExtra(OutgoingCallBroadcaster.EXTRA_ALREADY_CALLED, false);
      if (alreadyCalled) {
        if (DBG) Log.v(TAG, "CALL already placed -- returning.");
        return;
      }

      // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData
      // is used as the actual number to call. (If null, no call will be
      // placed.)

      number = getResultData();
      if (VDBG) Log.v(TAG, "- got number from resultData: '" + number + "'");

      final PhoneApp app = PhoneApp.getInstance();

      if (isOtaActive()) {
        // OTASP call is active. Don't allow new outgoing calls at all
        Log.w(TAG, "OTASP call is active: disallowing a new outgoing call.");
        return;
      }

      if (number == null) {
        if (DBG) Log.v(TAG, "CALL cancelled (null number), returning...");
        return;
      } else if (TelephonyCapabilities.supportsOtasp(app.phone)
          && (app.phone.getState() != Phone.State.IDLE)
          && (app.phone.isOtaSpNumber(number))) {
        if (DBG) Log.v(TAG, "Call is active, a 2nd OTA call cancelled -- returning.");
        return;
      } else if (PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, context)) {
        // Just like 3rd-party apps aren't allowed to place emergency
        // calls via the ACTION_CALL intent, we also don't allow 3rd
        // party apps to use the NEW_OUTGOING_CALL broadcast to rewrite
        // an outgoing call into an emergency number.
        Log.w(TAG, "Cannot modify outgoing call to emergency number " + number + ".");
        return;
      }

      originalUri = intent.getStringExtra(OutgoingCallBroadcaster.EXTRA_ORIGINAL_URI);
      if (originalUri == null) {
        Log.e(TAG, "Intent is missing EXTRA_ORIGINAL_URI -- returning.");
        return;
      }

      Uri uri = Uri.parse(originalUri);

      // We already called convertKeypadLettersToDigits() and
      // stripSeparators() way back in onCreate(), before we sent out the
      // NEW_OUTGOING_CALL broadcast.  But we need to do it again here
      // too, since the number might have been modified/rewritten during
      // the broadcast (and may now contain letters or separators again.)
      number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
      number = PhoneNumberUtils.stripSeparators(number);

      if (DBG) Log.v(TAG, "doReceive: proceeding with call...");
      if (VDBG) Log.v(TAG, "- uri: " + uri);
      if (VDBG) Log.v(TAG, "- actual number to dial: '" + number + "'");

      startSipCallOptionHandler(context, intent, uri, number);
    }
 public boolean isSimPinEnabled() {
   enforceReadPermission();
   return (PhoneApp.getInstance().isSimPinEnabled());
 }
  @Override
  protected void onCreate(Bundle icicle) {
    Log.i(TAG, "onCreate()...  intent = " + getIntent());
    super.onCreate(icicle);

    // Watch out: the intent action we get here should always be
    // ACTION_CALL_EMERGENCY, since the whole point of this activity
    // is for it to be launched using the same intent originally
    // passed to the InCallScreen, which will always be
    // ACTION_CALL_EMERGENCY when making an emergency call.
    //
    // If we ever get launched with any other action, especially if it's
    // "com.android.phone.InCallScreen.UNDEFINED" (as in bug 3094858), that
    // almost certainly indicates a logic bug in the InCallScreen.
    if (!Intent.ACTION_CALL_EMERGENCY.equals(getIntent().getAction())) {
      Log.w(
          TAG,
          "Unexpected intent action!  Should be ACTION_CALL_EMERGENCY, "
              + "but instead got: "
              + getIntent().getAction());
    }

    // setup the phone and get the retry count embedded in the intent.
    Phone phone = PhoneFactory.getDefaultPhone();
    int retryCount = getIntent().getIntExtra(EMERGENCY_CALL_RETRY_KEY, INITIAL_ATTEMPT);

    // create a new message object.
    EmergencyCallInfo eci = new EmergencyCallInfo();
    eci.phone = phone;
    eci.app = getApplication();
    eci.dialog = constructDialog(retryCount);

    // The Intent we're going to fire off to retry the call is the
    // same one that got us here (except that we *don't* explicitly
    // specify this class as the component!)
    eci.intent = getIntent().setComponent(null);
    // And we'll be firing this Intent from the PhoneApp's context
    // (see the startActivity() calls above) so the
    // FLAG_ACTIVITY_NEW_TASK flag is required.
    eci.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (DBG) Log.d(TAG, "- initial eci.intent: " + eci.intent);

    // create the handler.
    if (sHandler == null) {
      sHandler = new EmergencyCallEventHandler();
    }

    // If this is the initial attempt, we need to register for a radio state
    // change and turn the radio on.  Otherwise, this is just a retry, and
    // we simply wait the alloted time before sending the request to try
    // the call again.

    // Note: The radio logic ITSELF will try its best to put the emergency
    // call through once the radio is turned on.  The retry we have here
    // is in case it fails; the current constants we have include making
    // 6 attempts, with a 5 second delay between each.
    if (retryCount == INITIAL_ATTEMPT) {
      // place the number of pending retries in the intent.
      eci.intent.putExtra(EMERGENCY_CALL_RETRY_KEY, NUMBER_OF_RETRIES);
      int sub = PhoneApp.getInstance().getVoiceSubscriptionInService();
      eci.intent.putExtra(SUBSCRIPTION, sub);
      Log.d(TAG, "Attempting emergency call on sub :" + sub);

      // turn the radio on and listen for it to complete.
      phone.registerForServiceStateChanged(sHandler, EVENT_SERVICE_STATE_CHANGED, eci);

      // If airplane mode is on, we turn it off the same way that the
      // Settings activity turns it off.
      if (Settings.System.getInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) > 0) {
        if (DBG) Log.d(TAG, "Turning off airplane mode...");

        // Change the system setting
        Settings.System.putInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0);

        // Post the intent
        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intent.putExtra("state", false);
        sendBroadcast(intent);

        // Otherwise, for some strange reason the radio is just off, so
        // we just turn it back on.
      } else {
        if (DBG) Log.d(TAG, "Manually powering radio on...");
        phone.setRadioPower(true);
      }

    } else {
      // decrement and store the number of retries.
      if (DBG) Log.d(TAG, "Retry attempt...  retryCount = " + retryCount);
      eci.intent.putExtra(EMERGENCY_CALL_RETRY_KEY, (retryCount - 1));

      // get the message and attach the data, then wait the alloted
      // time and send.
      Message m = sHandler.obtainMessage(EVENT_TIMEOUT_EMERGENCY_CALL);
      m.obj = eci;
      sHandler.sendMessageDelayed(m, TIME_BETWEEN_RETRIES_MS);
    }
    finish();
  }
  @Override
  protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    PhoneApp app = PhoneApp.getInstance();
    addPreferencesFromResource(R.xml.msim_network_settings);

    mSubscription = getIntent().getIntExtra(SUBSCRIPTION_KEY, app.getDefaultSubscription());
    log("Settings onCreate subscription =" + mSubscription);
    mPhone = app.getPhone(mSubscription);
    mHandler = new MyHandler();

    // get UI object references
    PreferenceScreen prefSet = getPreferenceScreen();

    mButtonPreferredNetworkMode =
        (ListPreference) prefSet.findPreference(BUTTON_PREFERED_NETWORK_MODE);

    boolean isLteOnCdma = mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE;
    if (getResources().getBoolean(R.bool.world_phone) == true) {

      if (SystemProperties.getBoolean("ro.monkey", false)) {
        prefSet.removePreference(mButtonPreferredNetworkMode);
      } else {
        // set the listener for the mButtonPreferredNetworkMode list
        // preference so we can issue change Preferred Network Mode.
        mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this);

        // Get the networkMode from Settings.System and displays it
        int settingsNetworkMode =
            android.provider.Settings.Secure.getInt(
                mPhone.getContext().getContentResolver(),
                android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
                preferredNetworkMode);
        mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
        mCdmaOptions = new CdmaOptions(this, prefSet, mPhone);
        mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet, mSubscription);
      }
    } else {
      if (!isLteOnCdma) {
        prefSet.removePreference(mButtonPreferredNetworkMode);
      }
      int phoneType = mPhone.getPhoneType();
      if (phoneType == Phone.PHONE_TYPE_CDMA) {
        mCdmaOptions = new CdmaOptions(this, prefSet, mPhone);
        if (isLteOnCdma) {
          mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this);
          mButtonPreferredNetworkMode.setEntries(R.array.preferred_network_mode_choices_lte);
          mButtonPreferredNetworkMode.setEntryValues(R.array.preferred_network_mode_values_lte);
          int settingsNetworkMode =
              android.provider.Settings.Secure.getInt(
                  mPhone.getContext().getContentResolver(),
                  android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
                  preferredNetworkMode);
          mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
        }

      } else if (phoneType == Phone.PHONE_TYPE_GSM) {
        mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet, mSubscription);
      } else {
        throw new IllegalStateException("Unexpected phone type: " + phoneType);
      }
    }
  }
示例#15
0
        @Override
        public void handleMessage(Message msg) {
          switch (msg.what) {
            case EVENT_SIM_LOCKED:
              //                    mIsSimPinEnabled = true;
              //
              //                    if (Config.LOGV) Log.v(LOG_TAG, "show sim unlock panel");
              //                    SimPinUnlockPanel pinUnlockPanel = new SimPinUnlockPanel(
              //                            PhoneApp.getInstance());
              //                    pinUnlockPanel.show();
              break;

            case EVENT_SIM_ABSENT:
              // Don't need this now that the lock screen handles this case
              //                    if (Config.LOGV) Log.v(LOG_TAG, "show sim missing panel");
              //                    SimMissingPanel missingPanel = new SimMissingPanel(
              //                            PhoneApp.getInstance());
              //                    missingPanel.show();
              break;

            case EVENT_SIM_NETWORK_LOCKED:
              if (getResources().getBoolean(R.bool.ignore_sim_network_locked_events)) {
                // Some products don't have the concept of a "SIM network lock"
                Log.i(
                    LOG_TAG,
                    "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
                        + "not showing 'SIM network unlock' PIN entry screen");
              } else {
                // Normal case: show the "SIM network unlock" PIN entry screen.
                // The user won't be able to do anything else until
                // they enter a valid SIM network PIN.
                Log.i(LOG_TAG, "show sim depersonal panel");
                IccNetworkDepersonalizationPanel ndpPanel =
                    new IccNetworkDepersonalizationPanel(PhoneApp.getInstance());
                ndpPanel.show();
              }
              break;

            case EVENT_UPDATE_INCALL_NOTIFICATION:
              // Tell the NotificationMgr to update the "ongoing
              // call" icon in the status bar, if necessary.
              // Currently, this is triggered by a bluetooth headset
              // state change (since the status bar icon needs to
              // turn blue when bluetooth is active.)
              NotificationMgr.getDefault().updateInCallNotification();
              break;

            case EVENT_DATA_ROAMING_DISCONNECTED:
              NotificationMgr.getDefault().showDataDisconnectedRoaming();
              break;

            case EVENT_DATA_ROAMING_OK:
              NotificationMgr.getDefault().hideDataDisconnectedRoaming();
              break;

            case MMI_COMPLETE:
              onMMIComplete((AsyncResult) msg.obj);
              break;

            case MMI_CANCEL:
              PhoneUtils.cancelMmiCode(phone);
              break;

            case EVENT_WIRED_HEADSET_PLUG:
              // Since the presence of a wired headset or bluetooth affects the
              // speakerphone, update the "speaker" state.  We ONLY want to do
              // this on the wired headset connect / disconnect events for now
              // though, so we're only triggering on EVENT_WIRED_HEADSET_PLUG.
              if (!isHeadsetPlugged() && (mBtHandsfree == null || !mBtHandsfree.isAudioOn())) {
                // is the state is "not connected", restore the speaker state.
                PhoneUtils.restoreSpeakerMode(getApplicationContext());
              }
              NotificationMgr.getDefault().updateSpeakerNotification();
              break;

            case EVENT_SIM_STATE_CHANGED:
              // Marks the event where the SIM goes into ready state.
              // Right now, this is only used for the PUK-unlocking
              // process.
              if (msg.obj.equals(IccCard.INTENT_VALUE_ICC_READY)) {
                // when the right event is triggered and there
                // are UI objects in the foreground, we close
                // them to display the lock panel.
                if (mPUKEntryActivity != null) {
                  mPUKEntryActivity.finish();
                  mPUKEntryActivity = null;
                }
                if (mPUKEntryProgressDialog != null) {
                  mPUKEntryProgressDialog.dismiss();
                  mPUKEntryProgressDialog = null;
                }
              }
              break;

            case EVENT_UNSOL_CDMA_INFO_RECORD:
              // TODO: handle message here;
              break;
          }
        }
 /**
  * Public API to get SIMInfoWrapper instance
  *
  * @param context
  * @param isInsertSim
  * @return SIMInfoWrapper instance
  */
 static SIMInfoWrapper getDefault() {
   if (sSIMInfoWrapper == null) sSIMInfoWrapper = new SIMInfoWrapper(PhoneApp.getInstance());
   return sSIMInfoWrapper;
 }