Merge "Fixes crash null exception on land/seascape pinned orientations"
This commit is contained in:
committed by
Android (Google) Code Review
commit
df07d10609
@@ -132,6 +132,12 @@ oneway interface IStatusBar
|
||||
void clickQsTile(in ComponentName tile);
|
||||
void handleSystemKey(in int key);
|
||||
|
||||
/**
|
||||
* Methods to show toast messages for screen pinning
|
||||
*/
|
||||
void showPinningEnterExitToast(boolean entering);
|
||||
void showPinningEscapeToast();
|
||||
|
||||
void showShutdownUi(boolean isReboot, String reason);
|
||||
|
||||
// Used to show the dialog when FingerprintService starts authentication
|
||||
|
||||
@@ -81,6 +81,12 @@ interface IStatusBarService
|
||||
void clickTile(in ComponentName tile);
|
||||
void handleSystemKey(in int key);
|
||||
|
||||
/**
|
||||
* Methods to show toast messages for screen pinning
|
||||
*/
|
||||
void showPinningEnterExitToast(boolean entering);
|
||||
void showPinningEscapeToast();
|
||||
|
||||
// Used to show the dialog when FingerprintService starts authentication
|
||||
void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
|
||||
// Used to hide the dialog when a finger is authenticated
|
||||
|
||||
@@ -4423,15 +4423,6 @@
|
||||
<!-- DO NOT TRANSLATE -->
|
||||
<string name="date_picker_day_typeface">sans-serif-medium</string>
|
||||
|
||||
<!-- Notify use that they are in Lock-to-app -->
|
||||
<string name="lock_to_app_toast">To unpin this screen, touch & hold Back and Overview
|
||||
buttons</string>
|
||||
|
||||
<!-- Starting lock-to-app indication. -->
|
||||
<string name="lock_to_app_start">Screen pinned</string>
|
||||
<!-- Exting lock-to-app indication. -->
|
||||
<string name="lock_to_app_exit">Screen unpinned</string>
|
||||
|
||||
<!-- Lock-to-app unlock pin string -->
|
||||
<string name="lock_to_app_unlock_pin">Ask for PIN before unpinning</string>
|
||||
<!-- Lock-to-app unlock pattern string -->
|
||||
|
||||
@@ -767,9 +767,6 @@
|
||||
<java-symbol type="string" name="kilobyteShort" />
|
||||
<java-symbol type="string" name="last_month" />
|
||||
<java-symbol type="string" name="launchBrowserDefault" />
|
||||
<java-symbol type="string" name="lock_to_app_toast" />
|
||||
<java-symbol type="string" name="lock_to_app_start" />
|
||||
<java-symbol type="string" name="lock_to_app_exit" />
|
||||
<java-symbol type="string" name="lock_to_app_unlock_pin" />
|
||||
<java-symbol type="string" name="lock_to_app_unlock_pattern" />
|
||||
<java-symbol type="string" name="lock_to_app_unlock_password" />
|
||||
|
||||
@@ -84,7 +84,25 @@
|
||||
android:layout_height="@dimen/screen_pinning_request_button_height"
|
||||
android:layout_weight="0"
|
||||
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
|
||||
android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
|
||||
android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
|
||||
android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg_light"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:src="@drawable/screen_pinning_light_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingStart="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
|
||||
android:scaleType="matrix"
|
||||
android:src="@drawable/screen_pinning_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -78,7 +78,25 @@
|
||||
android:id="@+id/screen_pinning_home_group"
|
||||
android:layout_height="@dimen/screen_pinning_request_button_width"
|
||||
android:layout_width="@dimen/screen_pinning_request_button_height"
|
||||
android:layout_weight="0" >
|
||||
android:layout_weight="0"
|
||||
android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg_light"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:src="@drawable/screen_pinning_light_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
|
||||
android:src="@drawable/screen_pinning_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -80,7 +80,27 @@
|
||||
android:id="@+id/screen_pinning_home_group"
|
||||
android:layout_height="@dimen/screen_pinning_request_button_width"
|
||||
android:layout_width="@dimen/screen_pinning_request_button_height"
|
||||
android:layout_weight="0" >
|
||||
android:layout_weight="0"
|
||||
android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg_light"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:layout_marginLeft="@dimen/screen_pinning_request_seascape_padding_negative"
|
||||
android:src="@drawable/screen_pinning_light_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_pinning_home_bg"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:scaleType="matrix"
|
||||
android:layout_marginLeft="@dimen/screen_pinning_request_seascape_button_offset"
|
||||
android:paddingRight="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
|
||||
android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
|
||||
android:src="@drawable/screen_pinning_bg_circ" />
|
||||
|
||||
<ImageView
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -1281,12 +1281,23 @@
|
||||
<string name="screen_pinning_title">Screen is pinned</string>
|
||||
<!-- Screen pinning dialog description. -->
|
||||
<string name="screen_pinning_description">This keeps it in view until you unpin. Touch & hold Back and Overview to unpin.</string>
|
||||
<string name="screen_pinning_description_recents_invisible">This keeps it in view until you unpin. Touch & hold Back and Home to unpin.</string>
|
||||
<!-- Screen pinning dialog description. -->
|
||||
<string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch & hold Overview to unpin.</string>
|
||||
<string name="screen_pinning_description_recents_invisible_accessible">This keeps it in view until you unpin. Touch & hold Home to unpin.</string>
|
||||
<!-- Notify use that they are in Lock-to-app -->
|
||||
<string name="screen_pinning_toast">To unpin this screen, touch & hold Back and Overview
|
||||
buttons</string>
|
||||
<string name="screen_pinning_toast_recents_invisible">To unpin this screen, touch & hold Back
|
||||
and Home buttons</string>
|
||||
<!-- Screen pinning positive response. -->
|
||||
<string name="screen_pinning_positive">Got it</string>
|
||||
<!-- Screen pinning negative response. -->
|
||||
<string name="screen_pinning_negative">No thanks</string>
|
||||
<!-- Enter/Exiting screen pinning indication. -->
|
||||
<string name="screen_pinning_start">Screen pinned</string>
|
||||
<string name="screen_pinning_exit">Screen unpinned</string>
|
||||
|
||||
|
||||
<!-- Hide quick settings tile confirmation title -->
|
||||
<string name="quick_settings_reset_confirmation_title">Hide <xliff:g id="tile_label" example="Hotspot">%1$s</xliff:g>?</string>
|
||||
|
||||
@@ -15,13 +15,19 @@
|
||||
*/
|
||||
package com.android.systemui;
|
||||
|
||||
import android.annotation.StringRes;
|
||||
import android.content.Context;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
import static android.widget.Toast.Duration;
|
||||
|
||||
public class SysUIToast {
|
||||
|
||||
public static Toast makeText(Context context, CharSequence text, int duration) {
|
||||
public static Toast makeText(Context context, @StringRes int resId, @Duration int duration) {
|
||||
return makeText(context, context.getString(resId), duration);
|
||||
}
|
||||
|
||||
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
|
||||
Toast toast = Toast.makeText(context, text, duration);
|
||||
toast.getWindowParams().privateFlags |=
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
|
||||
@@ -23,15 +23,12 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Binder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Gravity;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
@@ -43,6 +40,9 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysUiServiceProvider;
|
||||
import com.android.systemui.statusbar.phone.NavigationBarView;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -233,11 +233,30 @@ public class ScreenPinningRequest implements View.OnClickListener {
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
|
||||
NavigationBarView navigationBarView = statusBar.getNavigationBarView();
|
||||
final boolean recentsVisible = navigationBarView != null
|
||||
&& navigationBarView.isRecentsButtonVisible();
|
||||
boolean touchExplorationEnabled = mAccessibilityService.isTouchExplorationEnabled();
|
||||
int descriptionStringResId;
|
||||
if (recentsVisible) {
|
||||
mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(VISIBLE);
|
||||
mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(INVISIBLE);
|
||||
mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(INVISIBLE);
|
||||
descriptionStringResId = touchExplorationEnabled
|
||||
? R.string.screen_pinning_description_accessible
|
||||
: R.string.screen_pinning_description;
|
||||
} else {
|
||||
mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(INVISIBLE);
|
||||
mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(VISIBLE);
|
||||
mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(VISIBLE);
|
||||
descriptionStringResId = touchExplorationEnabled
|
||||
? R.string.screen_pinning_description_recents_invisible_accessible
|
||||
: R.string.screen_pinning_description_recents_invisible;
|
||||
}
|
||||
|
||||
((TextView) mLayout.findViewById(R.id.screen_pinning_description))
|
||||
.setText(touchExplorationEnabled
|
||||
? R.string.screen_pinning_description_accessible
|
||||
: R.string.screen_pinning_description);
|
||||
.setText(descriptionStringResId);
|
||||
final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE;
|
||||
mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
|
||||
mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -90,6 +91,8 @@ public class CommandQueue extends IStatusBar.Stub {
|
||||
private static final int MSG_FINGERPRINT_ERROR = 42 << MSG_SHIFT;
|
||||
private static final int MSG_FINGERPRINT_HIDE = 43 << MSG_SHIFT;
|
||||
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
|
||||
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
|
||||
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
|
||||
|
||||
public static final int FLAG_EXCLUDE_NONE = 0;
|
||||
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
|
||||
@@ -148,6 +151,8 @@ public class CommandQueue extends IStatusBar.Stub {
|
||||
default void clickTile(ComponentName tile) { }
|
||||
|
||||
default void handleSystemKey(int arg1) { }
|
||||
default void showPinningEnterExitToast(boolean entering) { }
|
||||
default void showPinningEscapeToast() { }
|
||||
default void handleShowGlobalActionsMenu() { }
|
||||
default void handleShowShutdownUi(boolean isReboot, String reason) { }
|
||||
|
||||
@@ -452,6 +457,21 @@ public class CommandQueue extends IStatusBar.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEnterExitToast(boolean entering) {
|
||||
synchronized (mLock) {
|
||||
mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ENTER_EXIT, entering).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEscapeToast() {
|
||||
synchronized (mLock) {
|
||||
mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ESCAPE).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void showGlobalActionsMenu() {
|
||||
synchronized (mLock) {
|
||||
@@ -767,6 +787,16 @@ public class CommandQueue extends IStatusBar.Stub {
|
||||
mCallbacks.get(i).showChargingAnimation(msg.arg1);
|
||||
}
|
||||
break;
|
||||
case MSG_SHOW_PINNING_TOAST_ENTER_EXIT:
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
mCallbacks.get(i).showPinningEnterExitToast((Boolean) msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_SHOW_PINNING_TOAST_ESCAPE:
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
mCallbacks.get(i).showPinningEscapeToast();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,13 @@ import static android.app.StatusBarManager.windowStateToString;
|
||||
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
|
||||
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
|
||||
import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
|
||||
import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.IdRes;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerNative;
|
||||
@@ -69,6 +71,7 @@ import android.view.WindowManagerGlobal;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
@@ -153,6 +156,18 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
private Animator mRotateShowAnimator;
|
||||
private Animator mRotateHideAnimator;
|
||||
|
||||
private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
|
||||
@Override
|
||||
public void onConnectionChanged(boolean isConnected) {
|
||||
mNavigationBarView.onOverviewProxyConnectionChanged(isConnected);
|
||||
updateScreenPinningGestures();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStarted() {
|
||||
mNavigationBarView.setRecentsAnimationStarted(true);
|
||||
}
|
||||
};
|
||||
|
||||
// ----- Fragment Lifecycle Callbacks -----
|
||||
|
||||
@@ -239,12 +254,14 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
filter.addAction(Intent.ACTION_SCREEN_ON);
|
||||
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
|
||||
notifyNavigationBarScreenOn();
|
||||
mOverviewProxyService.addCallback(mOverviewProxyListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mNavigationBarView.getLightTransitionsController().destroy(getContext());
|
||||
mOverviewProxyService.removeCallback(mOverviewProxyListener);
|
||||
getContext().unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
|
||||
@@ -514,6 +531,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
if (masked != mDisabledFlags1) {
|
||||
mDisabledFlags1 = masked;
|
||||
if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
|
||||
updateScreenPinningGestures();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,7 +546,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
private boolean shouldDisableNavbarGestures() {
|
||||
return !mStatusBar.isDeviceProvisioned()
|
||||
|| (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
|
||||
|| mOverviewProxyService.getProxy() != null;
|
||||
|| mNavigationBarView.getRecentsButton().getVisibility() != View.VISIBLE;
|
||||
}
|
||||
|
||||
private void repositionNavigationBar() {
|
||||
@@ -540,6 +558,24 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
((View) mNavigationBarView.getParent()).getLayoutParams());
|
||||
}
|
||||
|
||||
private void updateScreenPinningGestures() {
|
||||
if (mNavigationBarView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the cancel pin gesture to home and back if recents button is invisible
|
||||
boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible();
|
||||
ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
|
||||
ButtonDispatcher backButton = mNavigationBarView.getBackButton();
|
||||
if (recentsVisible) {
|
||||
homeButton.setOnLongClickListener(this::onHomeLongClick);
|
||||
backButton.setOnLongClickListener(this::onLongPressBackRecents);
|
||||
} else {
|
||||
homeButton.setOnLongClickListener(this::onLongPressBackHome);
|
||||
backButton.setOnLongClickListener(this::onLongPressBackHome);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyNavigationBarScreenOn() {
|
||||
mNavigationBarView.notifyScreenOn();
|
||||
}
|
||||
@@ -555,11 +591,9 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
|
||||
ButtonDispatcher backButton = mNavigationBarView.getBackButton();
|
||||
backButton.setLongClickable(true);
|
||||
backButton.setOnLongClickListener(this::onLongPressBackRecents);
|
||||
|
||||
ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
|
||||
homeButton.setOnTouchListener(this::onHomeTouch);
|
||||
homeButton.setOnLongClickListener(this::onHomeLongClick);
|
||||
|
||||
ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
|
||||
accessibilityButton.setOnClickListener(this::onAccessibilityClick);
|
||||
@@ -569,6 +603,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
ButtonDispatcher rotateSuggestionButton = mNavigationBarView.getRotateSuggestionButton();
|
||||
rotateSuggestionButton.setOnClickListener(this::onRotateSuggestionClick);
|
||||
rotateSuggestionButton.setOnHoverListener(this::onRotateSuggestionHover);
|
||||
updateScreenPinningGestures();
|
||||
}
|
||||
|
||||
private boolean onHomeTouch(View v, MotionEvent event) {
|
||||
@@ -649,20 +684,29 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
mCommandQueue.toggleRecentApps();
|
||||
}
|
||||
|
||||
private boolean onLongPressBackHome(View v) {
|
||||
return onLongPressNavigationButtons(v, R.id.back, R.id.home);
|
||||
}
|
||||
|
||||
private boolean onLongPressBackRecents(View v) {
|
||||
return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles long-press of both back and recents. They are
|
||||
* handled together to capture them both being long-pressed
|
||||
* This handles long-press of both back and recents/home. Back is the common button with
|
||||
* combination of recents if it is visible or home if recents is invisible.
|
||||
* They are handled together to capture them both being long-pressed
|
||||
* at the same time to exit screen pinning (lock task).
|
||||
*
|
||||
* When accessibility mode is on, only a long-press from recents
|
||||
* When accessibility mode is on, only a long-press from recents/home
|
||||
* is required to exit.
|
||||
*
|
||||
* In all other circumstances we try to pass through long-press events
|
||||
* for Back, so that apps can still use it. Which can be from two things.
|
||||
* 1) Not currently in screen pinning (lock task).
|
||||
* 2) Back is long-pressed without recents.
|
||||
* 2) Back is long-pressed without recents/home.
|
||||
*/
|
||||
private boolean onLongPressBackRecents(View v) {
|
||||
private boolean onLongPressNavigationButtons(View v, @IdRes int btnId1, @IdRes int btnId2) {
|
||||
try {
|
||||
boolean sendBackLongPress = false;
|
||||
IActivityManager activityManager = ActivityManagerNative.getDefault();
|
||||
@@ -670,6 +714,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
boolean inLockTaskMode = activityManager.isInLockTaskMode();
|
||||
if (inLockTaskMode && !touchExplorationEnabled) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
// If we recently long-pressed the other button then they were
|
||||
// long-pressed 'together'
|
||||
if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
|
||||
@@ -677,26 +722,32 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
|
||||
// When exiting refresh disabled flags.
|
||||
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
|
||||
return true;
|
||||
} else if ((v.getId() == R.id.back)
|
||||
&& !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) {
|
||||
// If we aren't pressing recents right now then they presses
|
||||
// won't be together, so send the standard long-press action.
|
||||
sendBackLongPress = true;
|
||||
} else if (v.getId() == btnId1) {
|
||||
ButtonDispatcher button = btnId2 == R.id.recent_apps
|
||||
? mNavigationBarView.getRecentsButton()
|
||||
: mNavigationBarView.getHomeButton();
|
||||
if (!button.getCurrentView().isPressed()) {
|
||||
// If we aren't pressing recents/home right now then they presses
|
||||
// won't be together, so send the standard long-press action.
|
||||
sendBackLongPress = true;
|
||||
}
|
||||
}
|
||||
mLastLockToAppLongPress = time;
|
||||
} else {
|
||||
// If this is back still need to handle sending the long-press event.
|
||||
if (v.getId() == R.id.back) {
|
||||
if (v.getId() == btnId1) {
|
||||
sendBackLongPress = true;
|
||||
} else if (touchExplorationEnabled && inLockTaskMode) {
|
||||
// When in accessibility mode a long press that is recents (not back)
|
||||
// When in accessibility mode a long press that is recents/home (not back)
|
||||
// should stop lock task.
|
||||
activityManager.stopSystemLockTaskMode();
|
||||
// When exiting refresh disabled flags.
|
||||
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
|
||||
return true;
|
||||
} else if (v.getId() == R.id.recent_apps) {
|
||||
return onLongPressRecents();
|
||||
} else if (v.getId() == btnId2) {
|
||||
return btnId2 == R.id.recent_apps
|
||||
? onLongPressRecents()
|
||||
: onHomeLongClick(mNavigationBarView.getHomeButton().getCurrentView());
|
||||
}
|
||||
}
|
||||
if (sendBackLongPress) {
|
||||
|
||||
@@ -207,23 +207,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
}
|
||||
}
|
||||
|
||||
private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
|
||||
@Override
|
||||
public void onConnectionChanged(boolean isConnected) {
|
||||
updateSlippery();
|
||||
setDisabledFlags(mDisabledFlags, true);
|
||||
setUpSwipeUpOnboarding(isConnected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStarted() {
|
||||
mRecentsAnimationStarted = true;
|
||||
if (mSwipeUpOnboarding != null) {
|
||||
mSwipeUpOnboarding.onRecentsAnimationStarted();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public NavigationBarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
@@ -280,6 +263,19 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
notifyVerticalChangedListener(mVertical);
|
||||
}
|
||||
|
||||
public void setRecentsAnimationStarted(boolean started) {
|
||||
mRecentsAnimationStarted = started;
|
||||
if (mSwipeUpOnboarding != null) {
|
||||
mSwipeUpOnboarding.onRecentsAnimationStarted();
|
||||
}
|
||||
}
|
||||
|
||||
public void onConnectionChanged(boolean isConnected) {
|
||||
updateSlippery();
|
||||
setDisabledFlags(mDisabledFlags, true);
|
||||
setUpSwipeUpOnboarding(isConnected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (mGestureHelper.onTouchEvent(event)) {
|
||||
@@ -353,6 +349,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
return mButtonDispatchers;
|
||||
}
|
||||
|
||||
public boolean isRecentsButtonVisible() {
|
||||
return getRecentsButton().getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
private void updateCarModeIcons(Context ctx) {
|
||||
mBackCarModeIcon = getDrawable(ctx,
|
||||
R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
|
||||
@@ -613,6 +613,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
final ViewGroup navbarView = ((ViewGroup) getParent());
|
||||
final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
|
||||
.getLayoutParams();
|
||||
if (lp == null) {
|
||||
return;
|
||||
}
|
||||
if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
|
||||
lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
|
||||
changed = true;
|
||||
@@ -676,6 +679,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
}
|
||||
}
|
||||
|
||||
public void onOverviewProxyConnectionChanged(boolean isConnected) {
|
||||
setSlippery(!isConnected);
|
||||
setDisabledFlags(mDisabledFlags, true);
|
||||
setUpSwipeUpOnboarding(isConnected);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
mGestureHelper.onDraw(canvas);
|
||||
@@ -873,7 +882,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
onPluginDisconnected(null); // Create default gesture helper
|
||||
Dependency.get(PluginManager.class).addPluginListener(this,
|
||||
NavGesture.class, false /* Only one */);
|
||||
mOverviewProxyService.addCallback(mOverviewProxyListener);
|
||||
setUpSwipeUpOnboarding(mOverviewProxyService.getProxy() != null);
|
||||
}
|
||||
|
||||
@@ -884,7 +892,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
|
||||
if (mGestureHelper != null) {
|
||||
mGestureHelper.destroy();
|
||||
}
|
||||
mOverviewProxyService.removeCallback(mOverviewProxyListener);
|
||||
setUpSwipeUpOnboarding(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
* Copyright (C) 2018 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.am;
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
@@ -22,36 +22,37 @@ import android.util.Slog;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysUIToast;
|
||||
|
||||
/**
|
||||
* Helper to manage showing/hiding a image to notify them that they are entering or exiting screen
|
||||
* pinning mode. All exposed methods should be called from a handler thread.
|
||||
*/
|
||||
public class LockTaskNotify {
|
||||
private static final String TAG = "LockTaskNotify";
|
||||
public class ScreenPinningNotify {
|
||||
private static final String TAG = "ScreenPinningNotify";
|
||||
private static final long SHOW_TOAST_MINIMUM_INTERVAL = 1000;
|
||||
|
||||
private final Context mContext;
|
||||
private Toast mLastToast;
|
||||
private long mLastShowToastTime;
|
||||
|
||||
public LockTaskNotify(Context context) {
|
||||
public ScreenPinningNotify(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/** Show "Screen pinned" toast. */
|
||||
void showPinningStartToast() {
|
||||
makeAllUserToastAndShow(R.string.lock_to_app_start);
|
||||
makeAllUserToastAndShow(R.string.screen_pinning_start);
|
||||
}
|
||||
|
||||
/** Show "Screen unpinned" toast. */
|
||||
void showPinningExitToast() {
|
||||
makeAllUserToastAndShow(R.string.lock_to_app_exit);
|
||||
makeAllUserToastAndShow(R.string.screen_pinning_exit);
|
||||
}
|
||||
|
||||
/** Show a toast that describes the gesture the user should use to escape pinned mode. */
|
||||
void showEscapeToast() {
|
||||
void showEscapeToast(boolean isRecentsButtonVisible) {
|
||||
long showToastTime = SystemClock.elapsedRealtime();
|
||||
if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
|
||||
Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
|
||||
@@ -60,14 +61,14 @@ public class LockTaskNotify {
|
||||
if (mLastToast != null) {
|
||||
mLastToast.cancel();
|
||||
}
|
||||
mLastToast = makeAllUserToastAndShow(R.string.lock_to_app_toast);
|
||||
mLastToast = makeAllUserToastAndShow(isRecentsButtonVisible
|
||||
? R.string.screen_pinning_toast
|
||||
: R.string.screen_pinning_toast_recents_invisible);
|
||||
mLastShowToastTime = showToastTime;
|
||||
}
|
||||
|
||||
private Toast makeAllUserToastAndShow(int resId) {
|
||||
Toast toast = Toast.makeText(mContext, resId, Toast.LENGTH_LONG);
|
||||
toast.getWindowParams().privateFlags |=
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
Toast toast = SysUIToast.makeText(mContext, resId, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
return toast;
|
||||
}
|
||||
@@ -404,6 +404,13 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
protected NotificationEntryManager mEntryManager;
|
||||
protected NotificationViewHierarchyManager mViewHierarchyManager;
|
||||
|
||||
/**
|
||||
* Helper that is responsible for showing the right toast when a disallowed activity operation
|
||||
* occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
|
||||
* fully locked mode we only show that unlocking is blocked.
|
||||
*/
|
||||
private ScreenPinningNotify mScreenPinningNotify;
|
||||
|
||||
// for disabling the status bar
|
||||
private int mDisabled1 = 0;
|
||||
private int mDisabled2 = 0;
|
||||
@@ -830,7 +837,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
} catch (RemoteException ex) {
|
||||
// no window manager? good luck with that
|
||||
}
|
||||
|
||||
mScreenPinningNotify = new ScreenPinningNotify(mContext);
|
||||
mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker());
|
||||
mStackScroller.setStatusBar(this);
|
||||
mStackScroller.setGroupManager(mGroupManager);
|
||||
@@ -2141,6 +2148,21 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEnterExitToast(boolean entering) {
|
||||
if (entering) {
|
||||
mScreenPinningNotify.showPinningStartToast();
|
||||
} else {
|
||||
mScreenPinningNotify.showPinningExitToast();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEscapeToast() {
|
||||
mScreenPinningNotify.showEscapeToast(getNavigationBarView() == null
|
||||
|| getNavigationBarView().isRecentsButtonVisible());
|
||||
}
|
||||
|
||||
boolean panelsEnabled() {
|
||||
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0
|
||||
&& (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
|
||||
|
||||
@@ -38,6 +38,7 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
|
||||
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
|
||||
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
@@ -141,14 +142,6 @@ public class LockTaskController {
|
||||
@VisibleForTesting
|
||||
TelecomManager mTelecomManager;
|
||||
|
||||
/**
|
||||
* Helper that is responsible for showing the right toast when a disallowed activity operation
|
||||
* occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
|
||||
* fully locked mode we only show that unlocking is blocked.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
LockTaskNotify mLockTaskNotify;
|
||||
|
||||
/**
|
||||
* The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
|
||||
*
|
||||
@@ -475,7 +468,7 @@ public class LockTaskController {
|
||||
getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
|
||||
}
|
||||
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
|
||||
getLockTaskNotify().showPinningExitToast();
|
||||
getStatusBarService().showPinningEnterExitToast(false /* entering */);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
@@ -490,7 +483,11 @@ public class LockTaskController {
|
||||
*/
|
||||
void showLockTaskToast() {
|
||||
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
|
||||
mHandler.post(() -> getLockTaskNotify().showEscapeToast());
|
||||
try {
|
||||
getStatusBarService().showPinningEscapeToast();
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to send pinning escape toast", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,7 +579,7 @@ public class LockTaskController {
|
||||
// When lock task starts, we disable the status bars.
|
||||
try {
|
||||
if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
|
||||
getLockTaskNotify().showPinningStartToast();
|
||||
getStatusBarService().showPinningEnterExitToast(true /* entering */);
|
||||
}
|
||||
mLockTaskModeState = lockTaskModeState;
|
||||
setStatusBarState(lockTaskModeState, userId);
|
||||
@@ -835,15 +832,6 @@ public class LockTaskController {
|
||||
return mTelecomManager;
|
||||
}
|
||||
|
||||
// Should only be called on the handler thread
|
||||
@NonNull
|
||||
private LockTaskNotify getLockTaskNotify() {
|
||||
if (mLockTaskNotify == null) {
|
||||
mLockTaskNotify = new LockTaskNotify(mContext);
|
||||
}
|
||||
return mLockTaskNotify;
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw, String prefix) {
|
||||
pw.println(prefix + "LockTaskController");
|
||||
prefix = prefix + " ";
|
||||
|
||||
@@ -56,7 +56,6 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* A note on locking: We rely on the fact that calls onto mBar are oneway or
|
||||
* if they are local, that they just enqueue messages to not deadlock.
|
||||
@@ -524,6 +523,26 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEnterExitToast(boolean entering) throws RemoteException {
|
||||
if (mBar != null) {
|
||||
try {
|
||||
mBar.showPinningEnterExitToast(entering);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPinningEscapeToast() throws RemoteException {
|
||||
if (mBar != null) {
|
||||
try {
|
||||
mBar.showPinningEscapeToast();
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
|
||||
if (mBar != null) {
|
||||
|
||||
@@ -90,7 +90,6 @@ public class LockTaskControllerTest {
|
||||
@Mock private IStatusBarService mStatusBarService;
|
||||
@Mock private WindowManagerService mWindowManager;
|
||||
@Mock private LockPatternUtils mLockPatternUtils;
|
||||
@Mock private LockTaskNotify mLockTaskNotify;
|
||||
@Mock private StatusBarManagerInternal mStatusBarManagerInternal;
|
||||
@Mock private TelecomManager mTelecomManager;
|
||||
@Mock private RecentTasks mRecentTasks;
|
||||
@@ -123,7 +122,6 @@ public class LockTaskControllerTest {
|
||||
mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
|
||||
mLockTaskController.mTelecomManager = mTelecomManager;
|
||||
mLockTaskController.mLockPatternUtils = mLockPatternUtils;
|
||||
mLockTaskController.mLockTaskNotify = mLockTaskNotify;
|
||||
|
||||
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
|
||||
LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
|
||||
@@ -208,7 +206,7 @@ public class LockTaskControllerTest {
|
||||
// THEN lock task mode should be started
|
||||
verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
|
||||
// THEN screen pinning toast should be shown
|
||||
verify(mLockTaskNotify).showPinningStartToast();
|
||||
verify(mStatusBarService).showPinningEnterExitToast(true /* entering */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -377,7 +375,7 @@ public class LockTaskControllerTest {
|
||||
// THEN the keyguard should be shown
|
||||
verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL);
|
||||
// THEN screen pinning toast should be shown
|
||||
verify(mLockTaskNotify).showPinningExitToast();
|
||||
verify(mStatusBarService).showPinningEnterExitToast(false /* entering */);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user