Home | History | Annotate | Download | only in shortcuts
      1 /*
      2  * Copyright (C) 2016 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.dialer.shortcuts;
     18 
     19 import android.content.pm.PackageManager;
     20 import android.net.Uri;
     21 import android.os.Bundle;
     22 import android.support.v4.app.ActivityCompat;
     23 import android.widget.Toast;
     24 import com.android.dialer.callintent.CallInitiationType;
     25 import com.android.dialer.callintent.CallSpecificAppData;
     26 import com.android.dialer.common.LogUtil;
     27 import com.android.dialer.interactions.PhoneNumberInteraction;
     28 import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode;
     29 import com.android.dialer.util.TransactionSafeActivity;
     30 
     31 /**
     32  * Invisible activity launched when a shortcut is selected by user. Calls a contact based on URI.
     33  */
     34 public class CallContactActivity extends TransactionSafeActivity
     35     implements PhoneNumberInteraction.DisambigDialogDismissedListener,
     36         PhoneNumberInteraction.InteractionErrorListener,
     37         ActivityCompat.OnRequestPermissionsResultCallback {
     38 
     39   private static final String CONTACT_URI_KEY = "uri_key";
     40 
     41   private Uri contactUri;
     42 
     43   @Override
     44   public void onCreate(Bundle savedInstanceState) {
     45     super.onCreate(savedInstanceState);
     46 
     47     if ("com.android.dialer.shortcuts.CALL_CONTACT".equals(getIntent().getAction())) {
     48       if (Shortcuts.areDynamicShortcutsEnabled(this)) {
     49         LogUtil.i("CallContactActivity.onCreate", "shortcut clicked");
     50         contactUri = getIntent().getData();
     51         makeCall();
     52       } else {
     53         LogUtil.i("CallContactActivity.onCreate", "dynamic shortcuts disabled");
     54         finish();
     55       }
     56     }
     57   }
     58 
     59   @Override
     60   protected void onDestroy() {
     61     super.onDestroy();
     62     LogUtil.enterBlock("CallContactActivity.onDestroy");
     63   }
     64 
     65   /**
     66    * Attempt to make a call, finishing the activity if the required permissions are already granted.
     67    * If the required permissions are not already granted, the activity is not finished so that the
     68    * user can choose to grant or deny them.
     69    */
     70   private void makeCall() {
     71     CallSpecificAppData callSpecificAppData =
     72         CallSpecificAppData.newBuilder()
     73             .setCallInitiationType(CallInitiationType.Type.LAUNCHER_SHORTCUT)
     74             .build();
     75     PhoneNumberInteraction.startInteractionForPhoneCall(
     76         this, contactUri, false /* isVideoCall */, callSpecificAppData);
     77   }
     78 
     79   @Override
     80   public void onDisambigDialogDismissed() {
     81     finish();
     82   }
     83 
     84   @Override
     85   public void interactionError(@InteractionErrorCode int interactionErrorCode) {
     86     // Note: There is some subtlety to how contact lookup keys work that make it difficult to
     87     // distinguish the case of the contact missing from the case of the a contact not having a
     88     // number. For example, if a contact's phone number is deleted, subsequent lookups based on
     89     // lookup key will actually return no results because the phone number was part of the
     90     // lookup key. In this case, it would be inaccurate to say the contact can't be found though, so
     91     // in all cases we just say the contact can't be found or the contact doesn't have a number.
     92     switch (interactionErrorCode) {
     93       case InteractionErrorCode.CONTACT_NOT_FOUND:
     94       case InteractionErrorCode.CONTACT_HAS_NO_NUMBER:
     95         Toast.makeText(
     96                 this,
     97                 R.string.dialer_shortcut_contact_not_found_or_has_no_number,
     98                 Toast.LENGTH_SHORT)
     99             .show();
    100         break;
    101       case InteractionErrorCode.USER_LEAVING_ACTIVITY:
    102       case InteractionErrorCode.OTHER_ERROR:
    103       default:
    104         // If the user is leaving the activity or the error code was "other" there's no useful
    105         // information to display but we still need to finish this invisible activity.
    106         break;
    107     }
    108     finish();
    109   }
    110 
    111   @Override
    112   public void onSaveInstanceState(Bundle outState) {
    113     super.onSaveInstanceState(outState);
    114     outState.putParcelable(CONTACT_URI_KEY, contactUri);
    115   }
    116 
    117   @Override
    118   public void onRestoreInstanceState(Bundle savedInstanceState) {
    119     super.onRestoreInstanceState(savedInstanceState);
    120     if (savedInstanceState == null) {
    121       return;
    122     }
    123     contactUri = savedInstanceState.getParcelable(CONTACT_URI_KEY);
    124   }
    125 
    126   @Override
    127   public void onRequestPermissionsResult(
    128       int requestCode, String[] permissions, int[] grantResults) {
    129     switch (requestCode) {
    130       case PhoneNumberInteraction.REQUEST_READ_CONTACTS:
    131       case PhoneNumberInteraction.REQUEST_CALL_PHONE:
    132         {
    133           // If request is cancelled, the result arrays are empty.
    134           if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    135             makeCall();
    136           } else {
    137             Toast.makeText(this, R.string.dialer_shortcut_no_permissions, Toast.LENGTH_SHORT)
    138                 .show();
    139             finish();
    140           }
    141           break;
    142         }
    143       default:
    144         throw new IllegalStateException("Unsupported request code: " + requestCode);
    145     }
    146   }
    147 }
    148