diff options
Diffstat (limited to 'java')
10 files changed, 146 insertions, 37 deletions
diff --git a/java/com/android/incallui/AnswerScreenPresenter.java b/java/com/android/incallui/AnswerScreenPresenter.java index 58231d52b..b9a84ae5d 100644 --- a/java/com/android/incallui/AnswerScreenPresenter.java +++ b/java/com/android/incallui/AnswerScreenPresenter.java @@ -34,6 +34,7 @@ import com.android.incallui.answerproximitysensor.PseudoScreenState; import com.android.incallui.call.CallList; import com.android.incallui.call.DialerCall; import com.android.incallui.call.DialerCallListener; +import com.android.incallui.incalluilock.InCallUiLock; /** Manages changes for an incoming call screen. */ public class AnswerScreenPresenter @@ -72,19 +73,18 @@ public class AnswerScreenPresenter } @Override - public void onAnswerScreenUnready() { - call.removeCannedTextResponsesLoadedListener(this); + public InCallUiLock acquireInCallUiLock(String tag) { + return InCallPresenter.getInstance().acquireInCallUiLock(tag); } @Override - public void onDismissDialog() { - InCallPresenter.getInstance().onDismissDialog(); + public void onAnswerScreenUnready() { + call.removeCannedTextResponsesLoadedListener(this); } @Override public void onRejectCallWithMessage(String message) { call.reject(true /* rejectWithMessage */, message); - onDismissDialog(); addTimeoutCheck(); } diff --git a/java/com/android/incallui/AnswerScreenPresenterStub.java b/java/com/android/incallui/AnswerScreenPresenterStub.java index 2f9e60818..99f1f2c1d 100644 --- a/java/com/android/incallui/AnswerScreenPresenterStub.java +++ b/java/com/android/incallui/AnswerScreenPresenterStub.java @@ -18,6 +18,7 @@ package com.android.incallui; import android.support.annotation.FloatRange; import com.android.incallui.answer.protocol.AnswerScreenDelegate; +import com.android.incallui.incalluilock.InCallUiLock; /** * Stub implementation of the answer screen delegate. Used to keep the answer fragment visible when @@ -28,9 +29,6 @@ public class AnswerScreenPresenterStub implements AnswerScreenDelegate { public void onAnswerScreenUnready() {} @Override - public void onDismissDialog() {} - - @Override public void onRejectCallWithMessage(String message) {} @Override @@ -55,4 +53,9 @@ public class AnswerScreenPresenterStub implements AnswerScreenDelegate { public boolean isActionTimeout() { return false; } + + @Override + public InCallUiLock acquireInCallUiLock(String tag) { + return InCallPresenter.getInstance().acquireInCallUiLock(tag); + } } diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java index b82b6c994..2ba4d98a1 100644 --- a/java/com/android/incallui/InCallActivity.java +++ b/java/com/android/incallui/InCallActivity.java @@ -245,23 +245,16 @@ public class InCallActivity extends TransactionSafeFragmentActivity return true; } - if (common.hasPendingDialogs()) { - LogUtil.i( - "InCallActivity.shouldCloseActivityOnFinish", "dialog is visible, not closing activity"); - return false; - } - - AnswerScreen answerScreen = getAnswerScreen(); - if (answerScreen != null && answerScreen.hasPendingDialogs()) { + if (InCallPresenter.getInstance().isInCallUiLocked()) { LogUtil.i( "InCallActivity.shouldCloseActivityOnFinish", - "answer screen dialog is visible, not closing activity"); + "in call ui is locked, not closing activity"); return false; } LogUtil.i( "InCallActivity.shouldCloseActivityOnFinish", - "activity is visible and has no dialogs, allowing activity to close"); + "activity is visible and has no locks, allowing activity to close"); return true; } diff --git a/java/com/android/incallui/InCallActivityCommon.java b/java/com/android/incallui/InCallActivityCommon.java index 9e6271f3e..9ccda3251 100644 --- a/java/com/android/incallui/InCallActivityCommon.java +++ b/java/com/android/incallui/InCallActivityCommon.java @@ -60,6 +60,7 @@ import com.android.incallui.call.DialerCall; import com.android.incallui.call.DialerCall.State; import com.android.incallui.call.TelecomAdapter; import com.android.incallui.disconnectdialog.DisconnectMessage; +import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment; import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment.Callback; import java.lang.annotation.Retention; @@ -337,6 +338,9 @@ public class InCallActivityCommon { InCallPresenter.getInstance().onActivityStopped(); if (!isRecreating) { InCallPresenter.getInstance().onUiShowing(false); + if (dialog != null) { + dialog.dismiss(); + } } if (inCallActivity.isFinishing()) { InCallPresenter.getInstance().unsetActivity(inCallActivity); @@ -581,11 +585,13 @@ public class InCallActivityCommon { } this.dialog = dialog; + InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("showErrorDialog"); dialog.setOnDismissListener( new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { LogUtil.i("InCallActivityCommon.showErrorDialog", "dialog dismissed"); + lock.release(); onDialogDismissed(); } }); @@ -596,7 +602,6 @@ public class InCallActivityCommon { private void onDialogDismissed() { dialog = null; CallList.getInstance().onErrorDialogDismissed(); - InCallPresenter.getInstance().onDismissDialog(); } public void enableInCallOrientationEventListener(boolean enable) { @@ -672,6 +677,7 @@ public class InCallActivityCommon { (CheckBox) dialogCheckBoxView.findViewById(R.id.video_call_lte_to_wifi_failed_checkbox); wifiHandoverFailureCheckbox.setChecked(false); + InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("WifiFailedDialog"); dialog = builder .setView(dialogCheckBoxView) @@ -694,6 +700,7 @@ public class InCallActivityCommon { onDialogDismissed(); } }) + .setOnDismissListener((dialog) -> lock.release()) .create(); LogUtil.i("InCallActivityCommon.showWifiFailedDialog", "as dialog"); diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java index 4cc03f3dd..a0069a629 100644 --- a/java/com/android/incallui/InCallPresenter.java +++ b/java/com/android/incallui/InCallPresenter.java @@ -22,6 +22,7 @@ import android.graphics.Point; import android.os.Bundle; import android.os.Handler; import android.os.Trace; +import android.support.annotation.MainThread; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; @@ -34,6 +35,7 @@ import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; +import android.util.ArraySet; import android.view.Window; import android.view.WindowManager; import com.android.contacts.common.compat.CallCompat; @@ -41,6 +43,7 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; import com.android.dialer.blocking.FilteredNumberCompat; import com.android.dialer.blocking.FilteredNumbersUtil; +import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DefaultDialerExecutorFactory; import com.android.dialer.enrichedcall.EnrichedCallComponent; @@ -57,6 +60,7 @@ import com.android.incallui.call.DialerCall; import com.android.incallui.call.ExternalCallList; import com.android.incallui.call.TelecomAdapter; import com.android.incallui.disconnectdialog.DisconnectMessage; +import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.latencyreport.LatencyReport; import com.android.incallui.legacyblocking.BlockedNumberContentObserver; import com.android.incallui.spam.SpamCallListListener; @@ -1190,18 +1194,6 @@ public class InCallPresenter implements CallList.Listener { return true; } - /** - * A dialog could have prevented in-call screen from being previously finished. This function - * checks to see if there should be any UI left and if not attempts to tear down the UI. - */ - public void onDismissDialog() { - LogUtil.i("InCallPresenter.onDismissDialog", "Dialog dismissed"); - if (mInCallState == InCallState.NO_CALLS) { - attemptFinishActivity(); - attemptCleanup(); - } - } - /** Clears the previous fullscreen state. */ public void clearFullscreen() { mIsFullScreen = false; @@ -1491,7 +1483,10 @@ public class InCallPresenter implements CallList.Listener { mOrientationListeners.clear(); mInCallEventListeners.clear(); mInCallUiListeners.clear(); - + if (!mInCallUiLocks.isEmpty()) { + LogUtil.e("InCallPresenter.attemptCleanup", "held in call locks: " + mInCallUiLocks); + mInCallUiLocks.clear(); + } LogUtil.d("InCallPresenter.attemptCleanup", "finished"); } } @@ -1784,4 +1779,61 @@ public class InCallPresenter implements CallList.Listener { void onUiShowing(boolean showing); } + + private class InCallUiLockImpl implements InCallUiLock { + private final String tag; + + private InCallUiLockImpl(String tag) { + this.tag = tag; + } + + @MainThread + @Override + public void release() { + Assert.isMainThread(); + releaseInCallUiLock(InCallUiLockImpl.this); + } + + @Override + public String toString() { + return "InCallUiLock[" + tag + "]"; + } + } + + @MainThread + public InCallUiLock acquireInCallUiLock(String tag) { + Assert.isMainThread(); + InCallUiLock lock = new InCallUiLockImpl(tag); + mInCallUiLocks.add(lock); + return lock; + } + + @MainThread + private void releaseInCallUiLock(InCallUiLock lock) { + Assert.isMainThread(); + LogUtil.i("InCallPresenter.releaseInCallUiLock", "releasing %s", lock); + mInCallUiLocks.remove(lock); + if (mInCallUiLocks.isEmpty()) { + LogUtil.i("InCallPresenter.releaseInCallUiLock", "all locks released"); + if (mInCallState == InCallState.NO_CALLS) { + LogUtil.i("InCallPresenter.releaseInCallUiLock", "no more calls, finishing UI"); + attemptFinishActivity(); + attemptCleanup(); + } + } + } + + @MainThread + public boolean isInCallUiLocked() { + Assert.isMainThread(); + if (mInCallUiLocks.isEmpty()) { + return false; + } + for (InCallUiLock lock : mInCallUiLocks) { + LogUtil.i("InCallPresenter.isInCallUiLocked", "still locked by %s", lock); + } + return true; + } + + private final Set<InCallUiLock> mInCallUiLocks = new ArraySet<>(); } diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java index 18de72e8b..3476557ba 100644 --- a/java/com/android/incallui/answer/impl/AnswerFragment.java +++ b/java/com/android/incallui/answer/impl/AnswerFragment.java @@ -78,6 +78,7 @@ import com.android.incallui.incall.protocol.InCallScreenDelegateFactory; import com.android.incallui.incall.protocol.PrimaryCallState; import com.android.incallui.incall.protocol.PrimaryInfo; import com.android.incallui.incall.protocol.SecondaryInfo; +import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.maps.MapsComponent; import com.android.incallui.sessiondata.AvatarPresenter; import com.android.incallui.sessiondata.MultimediaFragment; @@ -977,6 +978,11 @@ public class AnswerFragment extends Fragment } @Override + public InCallUiLock acquireInCallUiLock(String tag) { + return answerScreenDelegate.acquireInCallUiLock(tag); + } + + @Override public void smsSelected(@Nullable CharSequence text) { LogUtil.i("AnswerFragment.smsSelected", null); textResponsesFragment = null; @@ -997,7 +1003,6 @@ public class AnswerFragment extends Fragment public void smsDismissed() { LogUtil.i("AnswerFragment.smsDismissed", null); textResponsesFragment = null; - answerScreenDelegate.onDismissDialog(); } @Override @@ -1014,7 +1019,6 @@ public class AnswerFragment extends Fragment public void customSmsDismissed() { LogUtil.i("AnswerFragment.customSmsDismissed", null); createCustomSmsDialogFragment = null; - answerScreenDelegate.onDismissDialog(); } private boolean canRejectCallWithSms() { diff --git a/java/com/android/incallui/answer/impl/CreateCustomSmsDialogFragment.java b/java/com/android/incallui/answer/impl/CreateCustomSmsDialogFragment.java index b49409258..73476f242 100644 --- a/java/com/android/incallui/answer/impl/CreateCustomSmsDialogFragment.java +++ b/java/com/android/incallui/answer/impl/CreateCustomSmsDialogFragment.java @@ -31,6 +31,7 @@ import android.view.WindowManager.LayoutParams; import android.widget.Button; import android.widget.EditText; import com.android.dialer.common.FragmentUtils; +import com.android.incallui.incalluilock.InCallUiLock; /** * Shows the dialog for users to enter a custom message when rejecting a call with an SMS message. @@ -40,6 +41,7 @@ public class CreateCustomSmsDialogFragment extends AppCompatDialogFragment { private static final String ARG_ENTERED_TEXT = "enteredText"; private EditText editText; + private InCallUiLock inCallUiLock; public static CreateCustomSmsDialogFragment newInstance() { return new CreateCustomSmsDialogFragment(); @@ -55,6 +57,11 @@ public class CreateCustomSmsDialogFragment extends AppCompatDialogFragment { if (savedInstanceState != null) { editText.setText(savedInstanceState.getCharSequence(ARG_ENTERED_TEXT)); } + + inCallUiLock = + FragmentUtils.getParentUnsafe( + CreateCustomSmsDialogFragment.this, CreateCustomSmsHolder.class) + .acquireInCallUiLock("CreateCustomSmsDialogFragment"); builder .setCancelable(true) .setView(view) @@ -124,12 +131,15 @@ public class CreateCustomSmsDialogFragment extends AppCompatDialogFragment { @Override public void onDismiss(DialogInterface dialogInterface) { super.onDismiss(dialogInterface); + inCallUiLock.release(); FragmentUtils.getParentUnsafe(this, CreateCustomSmsHolder.class).customSmsDismissed(); } /** Call back for {@link CreateCustomSmsDialogFragment} */ public interface CreateCustomSmsHolder { + InCallUiLock acquireInCallUiLock(String tag); + void customSmsCreated(@NonNull CharSequence text); void customSmsDismissed(); diff --git a/java/com/android/incallui/answer/impl/SmsBottomSheetFragment.java b/java/com/android/incallui/answer/impl/SmsBottomSheetFragment.java index 085430ea2..6742e4a36 100644 --- a/java/com/android/incallui/answer/impl/SmsBottomSheetFragment.java +++ b/java/com/android/incallui/answer/impl/SmsBottomSheetFragment.java @@ -36,6 +36,7 @@ import android.widget.TextView; import com.android.dialer.common.DpUtil; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; +import com.android.incallui.incalluilock.InCallUiLock; import java.util.ArrayList; import java.util.List; @@ -44,6 +45,8 @@ public class SmsBottomSheetFragment extends BottomSheetDialogFragment { private static final String ARG_OPTIONS = "options"; + private InCallUiLock inCallUiLock; + public static SmsBottomSheetFragment newInstance(@Nullable ArrayList<CharSequence> options) { SmsBottomSheetFragment fragment = new SmsBottomSheetFragment(); Bundle args = new Bundle(); @@ -80,6 +83,10 @@ public class SmsBottomSheetFragment extends BottomSheetDialogFragment { LogUtil.i("SmsBottomSheetFragment.onCreateDialog", null); Dialog dialog = super.onCreateDialog(savedInstanceState); dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + + inCallUiLock = + FragmentUtils.getParentUnsafe(SmsBottomSheetFragment.this, SmsSheetHolder.class) + .acquireInCallUiLock("SmsBottomSheetFragment"); return dialog; } @@ -88,7 +95,7 @@ public class SmsBottomSheetFragment extends BottomSheetDialogFragment { Context context = new ContextThemeWrapper(getContext(), getTheme()); TypedArray typedArray = context.obtainStyledAttributes(attrs); Drawable background = typedArray.getDrawable(0); - //noinspection ResourceType + // noinspection ResourceType typedArray.recycle(); TextView textView = new TextView(context); @@ -124,11 +131,14 @@ public class SmsBottomSheetFragment extends BottomSheetDialogFragment { public void onDismiss(DialogInterface dialogInterface) { super.onDismiss(dialogInterface); FragmentUtils.getParentUnsafe(this, SmsSheetHolder.class).smsDismissed(); + inCallUiLock.release(); } /** Callback interface for {@link SmsBottomSheetFragment} */ public interface SmsSheetHolder { + InCallUiLock acquireInCallUiLock(String tag); + void smsSelected(@Nullable CharSequence text); void smsDismissed(); diff --git a/java/com/android/incallui/answer/protocol/AnswerScreenDelegate.java b/java/com/android/incallui/answer/protocol/AnswerScreenDelegate.java index 5d2c415ed..5710922e0 100644 --- a/java/com/android/incallui/answer/protocol/AnswerScreenDelegate.java +++ b/java/com/android/incallui/answer/protocol/AnswerScreenDelegate.java @@ -17,14 +17,13 @@ package com.android.incallui.answer.protocol; import android.support.annotation.FloatRange; +import com.android.incallui.incalluilock.InCallUiLock; /** Callbacks implemented by the container app for this module. */ public interface AnswerScreenDelegate { void onAnswerScreenUnready(); - void onDismissDialog(); - void onRejectCallWithMessage(String message); void onAnswer(boolean answerVideoAsAudio); @@ -49,4 +48,6 @@ public interface AnswerScreenDelegate { /** Returns true if any answer/reject action timed out. */ boolean isActionTimeout(); + + InCallUiLock acquireInCallUiLock(String tag); } diff --git a/java/com/android/incallui/incalluilock/InCallUiLock.java b/java/com/android/incallui/incalluilock/InCallUiLock.java new file mode 100644 index 000000000..fbeae613a --- /dev/null +++ b/java/com/android/incallui/incalluilock/InCallUiLock.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.incalluilock; + +/** + * Prevents the {@link com.android.incallui.InCallActivity} from auto-finishing where there are no + * calls left. Acquired through {@link + * com.android.incallui.InCallPresenter#acquireInCallUiLock(String)}. Example: when a dialog is + * still being displayed to the user the InCallActivity should not disappear abruptly when the call + * ends, this lock should be held to keep the activity alive until it is dismissed. + */ +public interface InCallUiLock { + + void release(); +} |