• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             .setAllowAssistedDialing(true)
74             .setCallInitiationType(CallInitiationType.Type.LAUNCHER_SHORTCUT)
75             .build();
76     PhoneNumberInteraction.startInteractionForPhoneCall(
77         this, contactUri, false /* isVideoCall */, callSpecificAppData);
78   }
79 
80   @Override
onDisambigDialogDismissed()81   public void onDisambigDialogDismissed() {
82     finish();
83   }
84 
85   @Override
interactionError(@nteractionErrorCode int interactionErrorCode)86   public void interactionError(@InteractionErrorCode int interactionErrorCode) {
87     // Note: There is some subtlety to how contact lookup keys work that make it difficult to
88     // distinguish the case of the contact missing from the case of the a contact not having a
89     // number. For example, if a contact's phone number is deleted, subsequent lookups based on
90     // lookup key will actually return no results because the phone number was part of the
91     // lookup key. In this case, it would be inaccurate to say the contact can't be found though, so
92     // in all cases we just say the contact can't be found or the contact doesn't have a number.
93     switch (interactionErrorCode) {
94       case InteractionErrorCode.CONTACT_NOT_FOUND:
95       case InteractionErrorCode.CONTACT_HAS_NO_NUMBER:
96         Toast.makeText(
97                 this,
98                 R.string.dialer_shortcut_contact_not_found_or_has_no_number,
99                 Toast.LENGTH_SHORT)
100             .show();
101         break;
102       case InteractionErrorCode.USER_LEAVING_ACTIVITY:
103       case InteractionErrorCode.OTHER_ERROR:
104       default:
105         // If the user is leaving the activity or the error code was "other" there's no useful
106         // information to display but we still need to finish this invisible activity.
107         break;
108     }
109     finish();
110   }
111 
112   @Override
onSaveInstanceState(Bundle outState)113   public void onSaveInstanceState(Bundle outState) {
114     super.onSaveInstanceState(outState);
115     outState.putParcelable(CONTACT_URI_KEY, contactUri);
116   }
117 
118   @Override
onRestoreInstanceState(Bundle savedInstanceState)119   public void onRestoreInstanceState(Bundle savedInstanceState) {
120     super.onRestoreInstanceState(savedInstanceState);
121     if (savedInstanceState == null) {
122       return;
123     }
124     contactUri = savedInstanceState.getParcelable(CONTACT_URI_KEY);
125   }
126 
127   @Override
onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults)128   public void onRequestPermissionsResult(
129       int requestCode, String[] permissions, int[] grantResults) {
130     switch (requestCode) {
131       case PhoneNumberInteraction.REQUEST_READ_CONTACTS:
132       case PhoneNumberInteraction.REQUEST_CALL_PHONE:
133         {
134           // If request is cancelled, the result arrays are empty.
135           if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
136             makeCall();
137           } else {
138             Toast.makeText(this, R.string.dialer_shortcut_no_permissions, Toast.LENGTH_SHORT)
139                 .show();
140             finish();
141           }
142           break;
143         }
144       default:
145         throw new IllegalStateException("Unsupported request code: " + requestCode);
146     }
147   }
148 }
149