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 onCreate(Bundle savedInstanceState)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 onDestroy()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 */ makeCall()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 onDisambigDialogDismissed()80 public void onDisambigDialogDismissed() { 81 finish(); 82 } 83 84 @Override interactionError(@nteractionErrorCode int interactionErrorCode)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 onSaveInstanceState(Bundle outState)112 public void onSaveInstanceState(Bundle outState) { 113 super.onSaveInstanceState(outState); 114 outState.putParcelable(CONTACT_URI_KEY, contactUri); 115 } 116 117 @Override onRestoreInstanceState(Bundle savedInstanceState)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 onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults)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