OSDN Git Service

Merge "Add option to force remote input history" into nyc-dev
authorAdrian Roos <roosa@google.com>
Thu, 31 Mar 2016 18:34:53 +0000 (18:34 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 31 Mar 2016 18:34:54 +0000 (18:34 +0000)
1  2 
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java

@@@ -127,6 -127,8 +127,8 @@@ public abstract class BaseStatusBar ext
              SystemProperties.getBoolean("debug.enable_remote_input", true);
      public static final boolean ENABLE_CHILD_NOTIFICATIONS
              = SystemProperties.getBoolean("debug.child_notifs", true);
+     public static final boolean FORCE_REMOTE_INPUT_HISTORY =
+             SystemProperties.getBoolean("debug.force_remoteinput_history", false);
  
      protected static final int MSG_SHOW_RECENT_APPS = 1019;
      protected static final int MSG_HIDE_RECENT_APPS = 1020;
      protected boolean mVisible;
      protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
  
+     /**
+      * Notifications with keys in this set are not actually around anymore. We kept them around
+      * when they were canceled in response to a remote input interaction. This allows us to show
+      * what you replied and allows you to continue typing into it.
+      */
+     protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
      // mScreenOnFromKeyguard && mVisible.
      private boolean mVisibleToUser;
  
                      public void run() {
                          processForRemoteInput(sbn.getNotification());
                          String key = sbn.getKey();
+                         mKeysKeptForRemoteInput.remove(key);
                          boolean isUpdate = mNotificationData.get(key) != null;
                          // In case we don't allow child notifications, we ignore children of
                          // notifications that have a summary, since we're not going to show them
          }
      }
  
-     protected View bindVetoButtonClickListener(View row, StatusBarNotification n) {
+     protected View bindVetoButtonClickListener(View row, final StatusBarNotification n) {
          View vetoButton = row.findViewById(R.id.veto);
          final String _pkg = n.getPackageName();
          final String _tag = n.getTag();
                          mContext.getString(R.string.accessibility_notification_dismissed));
                  try {
                      mBarService.onNotificationClear(_pkg, _tag, _id, _userId);
+                     if (FORCE_REMOTE_INPUT_HISTORY
+                             && mKeysKeptForRemoteInput.contains(n.getKey())) {
+                         removeNotification(n.getKey(), null);
+                         mKeysKeptForRemoteInput.remove(n.getKey());
+                     }
  
                  } catch (RemoteException ex) {
                      // system process is dead if we're here.
      }
  
      @Override
 -    public void toggleKeyboardShortcutsMenu() {
 +    public void toggleKeyboardShortcutsMenu(int deviceId) {
          int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
          mHandler.removeMessages(msg);
 -        mHandler.sendEmptyMessage(msg);
 +        mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
      }
  
      /** Jumps to the next affiliated task in the group. */
          }
      }
  
 -    protected void toggleKeyboardShortcuts() {
 -        getKeyboardShortcuts().toggleKeyboardShortcuts();
 +    protected void toggleKeyboardShortcuts(int deviceId) {
 +        getKeyboardShortcuts().toggleKeyboardShortcuts(deviceId);
      }
  
      protected void cancelPreloadingRecents() {
                    showRecentsPreviousAffiliatedTask();
                    break;
               case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
 -                  toggleKeyboardShortcuts();
 +                  toggleKeyboardShortcuts(m.arg1);
                    break;
              }
          }
@@@ -120,7 -120,6 +120,7 @@@ import com.android.systemui.qs.QSContai
  import com.android.systemui.qs.QSPanel;
  import com.android.systemui.recents.ScreenPinningRequest;
  import com.android.systemui.recents.events.EventBus;
 +import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
  import com.android.systemui.recents.events.activity.UndockingTaskEvent;
  import com.android.systemui.stackdivider.Divider;
  import com.android.systemui.stackdivider.WindowManagerProxy;
@@@ -284,7 -283,7 +284,7 @@@ public class PhoneStatusBar extends Bas
      HotspotControllerImpl mHotspotController;
      RotationLockControllerImpl mRotationLockController;
      UserInfoController mUserInfoController;
 -    ZenModeController mZenModeController;
 +    protected ZenModeController mZenModeController;
      CastControllerImpl mCastController;
      VolumeComponent mVolumeComponent;
      KeyguardUserSwitcher mKeyguardUserSwitcher;
      Point mCurrentDisplaySize = new Point();
  
      protected StatusBarWindowView mStatusBarWindow;
 -    PhoneStatusBarView mStatusBarView;
 +    protected PhoneStatusBarView mStatusBarView;
      private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
      protected StatusBarWindowManager mStatusBarWindowManager;
      private UnlockMethodCache mUnlockMethodCache;
      int mPixelFormat;
      Object mQueueLock = new Object();
  
 -    StatusBarIconController mIconController;
 +    protected StatusBarIconController mIconController;
  
      // expanded notifications
      protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
  
      // top bar
      BaseStatusBarHeader mHeader;
 -    KeyguardStatusBarView mKeyguardStatusBar;
 +    protected KeyguardStatusBarView mKeyguardStatusBar;
      View mKeyguardStatusView;
      KeyguardBottomAreaView mKeyguardBottomArea;
      boolean mLeaveOpenOnKeyguardHide;
          mFalsingManager = FalsingManager.getInstance(mContext);
      }
  
 +    protected void createIconController() {
 +        mIconController = new StatusBarIconController(
 +                mContext, mStatusBarView, mKeyguardStatusBar, this);
 +    }
 +
      // ================================================================================
      // Constructing the view
      // ================================================================================
          mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
                  R.id.notification_panel);
          mNotificationPanel.setStatusBar(this);
 +        mNotificationPanel.setGroupManager(mGroupManager);
  
          mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
          mStatusBarView.setBar(this);
          // set the initial view visibility
          setAreThereNotifications();
  
 -        mIconController = new StatusBarIconController(
 -                mContext, mStatusBarView, mKeyguardStatusBar, this);
 +        createIconController();
  
          // Background thread for any controllers that need it.
          mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
                  mStatusBarKeyguardViewManager);
          mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
          mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
+         if (FORCE_REMOTE_INPUT_HISTORY) {
+             mRemoteInputController.addCallback(new RemoteInputController.Callback() {
+                 @Override
+                 public void onRemoteInputSent(Entry entry) {
+                     if (mKeysKeptForRemoteInput.contains(entry.key)) {
+                         removeNotification(entry.key, null);
+                     }
+                 }
+             });
+         }
          mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
          mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
      }
              clearCurrentMediaNotification();
              updateMediaMetaData(true, true);
          }
+         if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputController.isSpinning(key)) {
+             Entry entry = mNotificationData.get(key);
+             StatusBarNotification sbn = entry.notification;
+             Notification.Builder b = Notification.Builder
+                     .recoverBuilder(mContext, sbn.getNotification().clone());
+             CharSequence[] oldHistory = sbn.getNotification().extras
+                     .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+             CharSequence[] newHistory;
+             if (oldHistory == null) {
+                 newHistory = new CharSequence[1];
+             } else {
+                 newHistory = new CharSequence[oldHistory.length + 1];
+                 for (int i = 0; i < oldHistory.length; i++) {
+                     newHistory[i + 1] = oldHistory[i];
+                 }
+             }
+             newHistory[0] = String.valueOf(entry.remoteInputText);
+             b.setRemoteInputHistory(newHistory);
+             Notification newNotification = b.build();
+             // Undo any compatibility view inflation
+             newNotification.contentView = sbn.getNotification().contentView;
+             newNotification.bigContentView = sbn.getNotification().bigContentView;
+             newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
+             StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
+                     sbn.getOpPkg(),
+                     sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
+                     0, newNotification, sbn.getUser(), sbn.getPostTime());
+             updateNotification(newSbn, null);
+             mKeysKeptForRemoteInput.add(entry.key);
+             return;
+         }
          if (deferRemoval) {
              mLatestRankingMap = ranking;
              mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
          }
      }
  
 -    private int adjustDisableFlags(int state) {
 +    protected int adjustDisableFlags(int state) {
          if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
                  && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
              state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
      @Override
      public void appTransitionCancelled() {
          mIconController.appTransitionCancelled();
 +        EventBus.getDefault().send(new AppTransitionFinishedEvent());
      }
  
      @Override
      }
  
      @Override
 +    public void appTransitionFinished() {
 +        EventBus.getDefault().send(new AppTransitionFinishedEvent());
 +    }
 +
 +    @Override
      public void onCameraLaunchGestureDetected(int source) {
          mLastCameraLaunchSource = source;
          if (mStartedGoingToSleep) {
@@@ -46,7 -46,7 +46,7 @@@ import android.widget.TextView
  import com.android.systemui.R;
  import com.android.systemui.statusbar.NotificationData;
  import com.android.systemui.statusbar.RemoteInputController;
 -import com.android.systemui.statusbar.stack.LongPressCancelable;
 +import com.android.systemui.statusbar.stack.ScrollContainer;
  
  /**
   * Host for the remote input.
@@@ -67,9 -67,7 +67,9 @@@ public class RemoteInputView extends Li
      private RemoteInputController mController;
  
      private NotificationData.Entry mEntry;
 -    private LongPressCancelable mLongPressCancelable;
 +
 +    private ScrollContainer mScrollContainer;
 +    private View mScrollContainerChild;
  
      public RemoteInputView(Context context, AttributeSet attrs) {
          super(context, attrs);
          mEditText.setOnClickListener(this);
          mEditText.addTextChangedListener(this);
          mEditText.setInnerFocusable(false);
 -        mEditText.mDefocusListener = this;
 +        mEditText.mRemoteInputView = this;
      }
  
      private void sendRemoteInput() {
          mEditText.setEnabled(false);
          mSendButton.setVisibility(INVISIBLE);
          mProgressBar.setVisibility(VISIBLE);
+         mEntry.remoteInputText = mEditText.getText();
+         mController.addSpinning(mEntry.key);
          mController.removeRemoteInput(mEntry);
          mEditText.mShowImeOnInputConnection = false;
+         mController.remoteInputSent(mEntry);
  
          try {
              mPendingIntent.send(mContext, 0, fillInIntent);
              return;
          }
          mController.removeRemoteInput(mEntry);
+         mController.removeSpinning(mEntry.key);
      }
  
      public void setPendingIntent(PendingIntent pendingIntent) {
          mEditText.setEnabled(true);
          mSendButton.setVisibility(VISIBLE);
          mProgressBar.setVisibility(INVISIBLE);
+         mController.removeSpinning(mEntry.key);
          updateSendButton();
          onDefocus();
      }
      @Override
      public boolean onInterceptTouchEvent(MotionEvent ev) {
          if (ev.getAction() == MotionEvent.ACTION_DOWN) {
 -            if (mLongPressCancelable == null) {
 -                ViewParent p = getParent();
 -                while (p != null) {
 -                    if (p instanceof LongPressCancelable) {
 -                        mLongPressCancelable = (LongPressCancelable) p;
 -                        break;
 -                    }
 -                    p = p.getParent();
 -                }
 -            }
 -            if (mLongPressCancelable != null) {
 -                mLongPressCancelable.requestDisallowLongPress();
 +            findScrollContainer();
 +            if (mScrollContainer != null) {
 +                mScrollContainer.requestDisallowLongPress();
              }
          }
          return super.onInterceptTouchEvent(ev);
      }
  
 +    public boolean requestScrollTo() {
 +        findScrollContainer();
 +        mScrollContainer.scrollTo(mScrollContainerChild);
 +        return true;
 +    }
 +
 +    private void findScrollContainer() {
 +        if (mScrollContainer == null) {
 +            ViewParent p = this;
 +            while (p != null) {
 +                if (p.getParent() instanceof ScrollContainer) {
 +                    mScrollContainer = (ScrollContainer) p.getParent();
 +                    mScrollContainerChild = (View) p;
 +                    break;
 +                }
 +                p = p.getParent();
 +            }
 +        }
 +    }
 +
      /**
       * An EditText that changes appearance based on whether it's focusable and becomes
       * un-focusable whenever the user navigates away from it or it becomes invisible.
      public static class RemoteEditText extends EditText {
  
          private final Drawable mBackground;
 -        private RemoteInputView mDefocusListener;
 +        private RemoteInputView mRemoteInputView;
          boolean mShowImeOnInputConnection;
  
          public RemoteEditText(Context context, AttributeSet attrs) {
          }
  
          private void defocusIfNeeded() {
 -            if (mDefocusListener.mEntry.row.isChangingPosition()) {
 +            if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
                  return;
              }
              if (isFocusable() && isEnabled()) {
                  setInnerFocusable(false);
 -                if (mDefocusListener != null) {
 -                    mDefocusListener.onDefocus();
 +                if (mRemoteInputView != null) {
 +                    mRemoteInputView.onDefocus();
                  }
                  mShowImeOnInputConnection = false;
              }
          }
  
          @Override
 -        public boolean requestRectangleOnScreen(Rect r) {
 +        public void getFocusedRect(Rect r) {
 +            super.getFocusedRect(r);
              r.top = mScrollY;
              r.bottom = mScrollY + (mBottom - mTop);
 -            return super.requestRectangleOnScreen(r);
          }
  
          @Override
 -        public void getFocusedRect(Rect r) {
 -            super.getFocusedRect(r);
 -            r.top = mScrollY;
 -            r.bottom = mScrollY + (mBottom - mTop);
 +        public boolean requestRectangleOnScreen(Rect rectangle) {
 +            return mRemoteInputView.requestScrollTo();
          }
  
          @Override