Merge "Add custom call type affordance to TestActivity." into ub-contactsdialer-a-dev
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index f8fb17f..6f8f341 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -34,7 +34,6 @@
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.telecom.PhoneAccount;
-import android.telecom.TelecomManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -159,8 +158,6 @@
*/
private SmartDialSearchFragment mSmartDialSearchFragment;
- private boolean mIsVisible;
-
/**
* Animation that slides in.
*/
@@ -370,7 +367,6 @@
TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY());
}
return super.dispatchTouchEvent(ev);
-
}
@Override
@@ -566,25 +562,6 @@
}
@Override
- protected void onStart() {
- super.onStart();
- mIsVisible = true;
- }
-
- @Override
- protected void onStop() {
- mIsVisible = false;
- super.onStop();
- }
-
- /**
- * Returns true when the Activity is currently visible (between onStart and onStop).
- */
- /* package */ boolean isVisible() {
- return mIsVisible;
- }
-
- @Override
protected void onPause() {
if (mClearSearchOnPause) {
hideDialpadAndSearchUi();
@@ -598,7 +575,6 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
- mIsVisible = false;
super.onSaveInstanceState(outState);
outState.putString(KEY_SEARCH_QUERY, mSearchQuery);
outState.putBoolean(KEY_IN_REGULAR_SEARCH_UI, mInRegularSearch);
@@ -671,7 +647,7 @@
@Override
public boolean onMenuItemClick(MenuItem item) {
- if (!isVisible()) {
+ if (!isSafeToCommitTransactions()) {
return true;
}
@@ -693,8 +669,13 @@
// involve querying a {@link ProviderStatusLoader}, which we don't want to do right
// now in Dialtacts for (potential) performance reasons. Compare with how it is
// done in {@link PeopleActivity}.
- ImportExportDialogFragment.show(getFragmentManager(), true,
- DialtactsActivity.class);
+ if (mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_SPEED_DIAL) {
+ ImportExportDialogFragment.show(getFragmentManager(), true,
+ DialtactsActivity.class, ImportExportDialogFragment.EXPORT_MODE_FAVORITES);
+ } else {
+ ImportExportDialogFragment.show(getFragmentManager(), true,
+ DialtactsActivity.class, ImportExportDialogFragment.EXPORT_MODE_DEFAULT);
+ }
return true;
case R.id.menu_clear_frequents:
ClearFrequentsDialog.show(getFragmentManager());
@@ -929,7 +910,7 @@
final boolean callKey = Intent.ACTION_CALL_BUTTON.equals(intent.getAction());
if (callKey) {
- getTelecomManager().showInCallScreen(false);
+ TelecomUtil.showInCallScreen(this, false);
return true;
}
@@ -1340,10 +1321,6 @@
public void onPageScrollStateChanged(int state) {
}
- private TelecomManager getTelecomManager() {
- return (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
- }
-
@Override
public boolean isActionBarShowing() {
return mActionBarController.isActionBarShowing();
diff --git a/src/com/android/dialer/SpecialCharSequenceMgr.java b/src/com/android/dialer/SpecialCharSequenceMgr.java
index 31aa5c3..994829a 100644
--- a/src/com/android/dialer/SpecialCharSequenceMgr.java
+++ b/src/com/android/dialer/SpecialCharSequenceMgr.java
@@ -32,7 +32,6 @@
import android.provider.Settings;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -48,7 +47,6 @@
import com.android.dialer.calllog.PhoneAccountUtils;
import com.android.dialer.util.TelecomUtil;
-import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -91,13 +89,13 @@
private static QueryHandler sPreviousAdnQueryHandler;
public static class HandleAdnEntryAccountSelectedCallback extends SelectPhoneAccountListener{
- final private TelecomManager mTelecomManager;
+ final private Context mContext;
final private QueryHandler mQueryHandler;
final private SimContactQueryCookie mCookie;
- public HandleAdnEntryAccountSelectedCallback(TelecomManager telecomManager,
+ public HandleAdnEntryAccountSelectedCallback(Context context,
QueryHandler queryHandler, SimContactQueryCookie cookie) {
- mTelecomManager = telecomManager;
+ mContext = context;
mQueryHandler = queryHandler;
mCookie = cookie;
}
@@ -105,7 +103,7 @@
@Override
public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
boolean setDefault) {
- Uri uri = mTelecomManager.getAdnUriForPhoneAccount(selectedAccountHandle);
+ Uri uri = TelecomUtil.getAdnUriForPhoneAccount(mContext, selectedAccountHandle);
handleAdnQuery(mQueryHandler, mCookie, uri);
// TODO: Show error dialog if result isn't valid.
}
@@ -193,6 +191,7 @@
* and query cancel handler implemented in {@link SimContactQueryCookie}.
*/
static boolean handleAdnEntry(Context context, String input, EditText textField) {
+ context = context.getApplicationContext();
/* ADN entries are of the form "N(N)(N)#" */
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -245,20 +244,19 @@
sc.progressDialog.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(context);
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ TelecomUtil.getDefaultOutgoingPhoneAccount(context,
+ PhoneAccount.SCHEME_TEL));
if (subscriptionAccountHandles.size() == 1 || hasUserSelectedDefault) {
- Uri uri = telecomManager.getAdnUriForPhoneAccount(null);
+ Uri uri = TelecomUtil.getAdnUriForPhoneAccount(context, null);
handleAdnQuery(handler, sc, uri);
} else if (subscriptionAccountHandles.size() > 1){
SelectPhoneAccountListener callback =
- new HandleAdnEntryAccountSelectedCallback(telecomManager, handler, sc);
+ new HandleAdnEntryAccountSelectedCallback(context, handler, sc);
DialogFragment dialogFragment = SelectPhoneAccountDialogFragment.newInstance(
subscriptionAccountHandles, callback);
@@ -299,12 +297,10 @@
static boolean handlePinEntry(final Context context, final String input) {
if ((input.startsWith("**04") || input.startsWith("**05")) && input.endsWith("#")) {
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(context);
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_TEL));
if (subscriptionAccountHandles.size() == 1 || hasUserSelectedDefault) {
// Don't bring up the dialog for single-SIM or if the default outgoing account is
diff --git a/src/com/android/dialer/calllog/CallLogActivity.java b/src/com/android/dialer/calllog/CallLogActivity.java
index ad795f9..2bcd8d4 100644
--- a/src/com/android/dialer/calllog/CallLogActivity.java
+++ b/src/com/android/dialer/calllog/CallLogActivity.java
@@ -27,7 +27,6 @@
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -40,16 +39,15 @@
import com.android.contacts.commonbind.analytics.AnalyticsUtil;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
+import com.android.dialer.TransactionSafeActivity;
-public class CallLogActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
+public class CallLogActivity extends TransactionSafeActivity implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private ViewPagerTabs mViewPagerTabs;
private ViewPagerAdapter mViewPagerAdapter;
private CallLogFragment mAllCallsFragment;
private CallLogFragment mMissedCallsFragment;
- private boolean mIsVisible;
-
private String[] mTabTitles;
private static final int TAB_INDEX_ALL = 0;
@@ -163,31 +161,6 @@
}
@Override
- protected void onStart() {
- super.onStart();
- mIsVisible = false;
- }
-
- @Override
- protected void onStop() {
- mIsVisible = false;
- super.onStop();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- mIsVisible = false;
- super.onSaveInstanceState(outState);
- }
-
- /**
- * Returns true when the Activity is currently visible (between onStart and onStop).
- */
- /* package */ boolean isVisible() {
- return mIsVisible;
- }
-
- @Override
public boolean onCreateOptionsMenu(Menu menu) {
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.call_log_options, menu);
@@ -207,7 +180,7 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (!isVisible()) {
+ if (!isSafeToCommitTransactions()) {
return true;
}
diff --git a/src/com/android/dialer/calllog/PhoneAccountUtils.java b/src/com/android/dialer/calllog/PhoneAccountUtils.java
index 143d13e..ceadabc 100644
--- a/src/com/android/dialer/calllog/PhoneAccountUtils.java
+++ b/src/com/android/dialer/calllog/PhoneAccountUtils.java
@@ -23,6 +23,9 @@
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import com.android.contacts.common.util.PermissionsUtil;
+import com.android.dialer.util.TelecomUtil;
+
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +41,8 @@
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> subscriptionAccountHandles = new ArrayList<PhoneAccountHandle>();
- List<PhoneAccountHandle> accountHandles = telecomManager.getCallCapablePhoneAccounts();
+ final List<PhoneAccountHandle> accountHandles =
+ TelecomUtil.getCallCapablePhoneAccounts(context);
for (PhoneAccountHandle accountHandle : accountHandles) {
PhoneAccount account = telecomManager.getPhoneAccount(accountHandle);
if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 54e4b89..9c77f30 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -42,7 +42,6 @@
import android.provider.Settings;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.Editable;
@@ -274,10 +273,6 @@
return (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
}
- private TelecomManager getTelecomManager() {
- return (TelecomManager) getActivity().getSystemService(Context.TELECOM_SERVICE);
- }
-
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
mWasEmptyBeforeTextChange = TextUtils.isEmpty(s);
@@ -980,7 +975,7 @@
List<PhoneAccountHandle> subscriptionAccountHandles =
PhoneAccountUtils.getSubscriptionPhoneAccounts(getActivity());
boolean hasUserSelectedDefault = subscriptionAccountHandles.contains(
- getTelecomManager().getDefaultOutgoingPhoneAccount(
+ TelecomUtil.getDefaultOutgoingPhoneAccount(getActivity(),
PhoneAccount.SCHEME_VOICEMAIL));
boolean needsAccountDisambiguation = subscriptionAccountHandles.size() > 1
&& !hasUserSelectedDefault;
@@ -1462,7 +1457,7 @@
* or "return to call" from the dialpad chooser.
*/
private void returnToInCallScreen(boolean showDialpad) {
- getTelecomManager().showInCallScreen(showDialpad);
+ TelecomUtil.showInCallScreen(getActivity(), showDialpad);
// Finally, finish() ourselves so that we don't stay on the
// activity stack.
@@ -1579,20 +1574,19 @@
*
* @return true if voicemail is enabled and accessible. Note that this can be false
* "temporarily" after the app boot.
- * @see TelecomManager#getVoiceMailNumber(PhoneAccountHandle)
*/
private boolean isVoicemailAvailable() {
try {
PhoneAccountHandle defaultUserSelectedAccount =
- getTelecomManager().getDefaultOutgoingPhoneAccount(
+ TelecomUtil.getDefaultOutgoingPhoneAccount(getActivity(),
PhoneAccount.SCHEME_VOICEMAIL);
if (defaultUserSelectedAccount == null) {
// In a single-SIM phone, there is no default outgoing phone account selected by
// the user, so just call TelephonyManager#getVoicemailNumber directly.
return !TextUtils.isEmpty(getTelephonyManager().getVoiceMailNumber());
} else {
- return !TextUtils.isEmpty(
- getTelecomManager().getVoiceMailNumber(defaultUserSelectedAccount));
+ return !TextUtils.isEmpty(TelecomUtil.getVoicemailNumber(getActivity(),
+ defaultUserSelectedAccount));
}
} catch (SecurityException se) {
// Possibly no READ_PHONE_STATE privilege.
diff --git a/src/com/android/dialer/settings/AppCompatPreferenceActivity.java b/src/com/android/dialer/settings/AppCompatPreferenceActivity.java
index 804d477..4e5d9c9 100644
--- a/src/com/android/dialer/settings/AppCompatPreferenceActivity.java
+++ b/src/com/android/dialer/settings/AppCompatPreferenceActivity.java
@@ -32,11 +32,14 @@
public class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
+ private boolean mIsSafeToCommitTransactions;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
+ mIsSafeToCommitTransactions = true;
}
@Override
@@ -119,4 +122,34 @@
}
return mDelegate;
}
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mIsSafeToCommitTransactions = true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mIsSafeToCommitTransactions = true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mIsSafeToCommitTransactions = false;
+ }
+
+ /**
+ * Returns true if it is safe to commit {@link FragmentTransaction}s at this time, based on
+ * whether {@link Activity#onSaveInstanceState} has been called or not.
+ *
+ * Make sure that the current activity calls into
+ * {@link super.onSaveInstanceState(Bundle outState)} (if that method is overridden),
+ * so the flag is properly set.
+ */
+ public boolean isSafeToCommitTransactions() {
+ return mIsSafeToCommitTransactions;
+ }
}
diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java
index 2b72772..58b0ab8 100644
--- a/src/com/android/dialer/settings/DialerSettingsActivity.java
+++ b/src/com/android/dialer/settings/DialerSettingsActivity.java
@@ -131,6 +131,14 @@
}
@Override
+ public void onBackPressed() {
+ if (!isSafeToCommitTransactions()) {
+ return;
+ }
+ super.onBackPressed();
+ }
+
+ @Override
protected boolean isValidFragment(String fragmentName) {
return true;
}
diff --git a/src/com/android/dialer/util/DialerUtils.java b/src/com/android/dialer/util/DialerUtils.java
index 8870f76..3d5c257 100644
--- a/src/com/android/dialer/util/DialerUtils.java
+++ b/src/com/android/dialer/util/DialerUtils.java
@@ -86,11 +86,10 @@
extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
}
- final TelecomManager tm =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
- if (TelecomUtil.hasCallPhonePermission(context)) {
- tm.placeCall(intent.getData(), intent.getExtras());
- } else {
+
+ final boolean hasCallPermission = TelecomUtil.placeCall(context, intent.getData(),
+ intent.getExtras());
+ if (!hasCallPermission) {
// TODO: Make calling activity show request permission dialog and handle
// callback results appropriately.
Toast.makeText(context, "Cannot place call without Phone permission",
diff --git a/src/com/android/dialer/util/PhoneNumberUtil.java b/src/com/android/dialer/util/PhoneNumberUtil.java
index 539d8b9..2699803 100644
--- a/src/com/android/dialer/util/PhoneNumberUtil.java
+++ b/src/com/android/dialer/util/PhoneNumberUtil.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.provider.CallLog;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -55,10 +54,7 @@
if (TextUtils.isEmpty(number)) {
return false;
}
-
- final TelecomManager telecomManager =
- (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
- return telecomManager.isVoiceMailNumber(accountHandle, number.toString());
+ return TelecomUtil.isVoicemailNumber(context, accountHandle, number.toString());
}
/**
diff --git a/src/com/android/dialer/util/TelecomUtil.java b/src/com/android/dialer/util/TelecomUtil.java
index 43b9a72..bab1ade 100644
--- a/src/com/android/dialer/util/TelecomUtil.java
+++ b/src/com/android/dialer/util/TelecomUtil.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.CallLog.Calls;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -29,10 +30,27 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * Performs permission checks before calling into TelecomManager. Each method is self-explanatory -
+ * perform the required check and return the fallback default if the permission is missing,
+ * otherwise return the value from TelecomManager.
+ *
+ */
public class TelecomUtil {
private static final String TAG = "TelecomUtil";
private static boolean sWarningLogged = false;
+ public static void showInCallScreen(Context context, boolean showDialpad) {
+ if (hasReadPhoneStatePermission(context)) {
+ try {
+ getTelecomManager(context).showInCallScreen(showDialpad);
+ } catch (SecurityException e) {
+ // Just in case
+ Log.w(TAG, "TelecomManager.showInCallScreen called without permission.");
+ }
+ }
+ }
+
public static void silenceRinger(Context context) {
if (hasModifyPhoneStatePermission(context)) {
try {
@@ -81,6 +99,14 @@
return false;
}
+ public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(Context context,
+ String uriScheme) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).getDefaultOutgoingPhoneAccount(uriScheme);
+ }
+ return null;
+ }
+
public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(Context context) {
if (hasReadPhoneStatePermission(context)) {
return getTelecomManager(context).getCallCapablePhoneAccounts();
@@ -95,6 +121,39 @@
return false;
}
+ public static boolean isVoicemailNumber(Context context, PhoneAccountHandle accountHandle,
+ String number) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).isVoiceMailNumber(accountHandle, number);
+ }
+ return false;
+ }
+
+ public static String getVoicemailNumber(Context context, PhoneAccountHandle accountHandle) {
+ if (hasReadPhoneStatePermission(context)) {
+ return getTelecomManager(context).getVoiceMailNumber(accountHandle);
+ }
+ return null;
+ }
+
+ /**
+ * Tries to place a call using the {@link TelecomManager}.
+ *
+ * @param context a valid context.
+ * @param address Handle to call.
+ * @param extras Bundle of extras to attach to the call intent.
+ *
+ * @return {@code true} if we successfully attempted to place the call, {@code false} if it
+ * failed due to a permission check.
+ */
+ public static boolean placeCall(Context context, Uri address, Bundle extras) {
+ if (hasCallPhonePermission(context)) {
+ getTelecomManager(context).placeCall(address, extras);
+ return true;
+ }
+ return false;
+ }
+
public static Uri getCallLogUri(Context context) {
return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL
: Calls.CONTENT_URI;
diff --git a/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java b/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
index 5184930..c8d6403 100644
--- a/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
+++ b/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
@@ -119,7 +119,7 @@
// Delete row
int rows = mResolver.delete(
FilteredNumberContract.FilteredNumber.CONTENT_URI,
- "id = ?",
+ FilteredNumberContract.FilteredNumberColumns._ID + " = ?",
new String[]{Long.toString(id)});
assertEquals(rows, 1);