Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f14fa1ec authored by Yohei Yukawa's avatar Yohei Yukawa Committed by Android (Google) Code Review
Browse files

Merge "Stop lying about hardware keyboard presence."

parents 918343b5 7b739a80
Loading
Loading
Loading
Loading
+120 −8
Original line number Diff line number Diff line
@@ -19,16 +19,22 @@ package android.inputmethodservice;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.Region;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.SystemClock;
@@ -68,6 +74,8 @@ import android.widget.LinearLayout;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * InputMethodService provides a standard implementation of an InputMethod,
@@ -633,6 +641,97 @@ public class InputMethodService extends AbstractInputMethodService {
        public int touchableInsets;
    }

    /**
     * A {@link ContentObserver} to monitor {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD}.
     *
     * <p>Note that {@link Settings.Secure#SHOW_IME_WITH_HARD_KEYBOARD} is not a public API.
     * Basically this functionality still needs to be considered as implementation details.</p>
     */
    @MainThread
    private static final class SettingsObserver extends ContentObserver {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({
                ShowImeWithHardKeyboardType.UNKNOWN,
                ShowImeWithHardKeyboardType.FALSE,
                ShowImeWithHardKeyboardType.TRUE,
        })
        private @interface ShowImeWithHardKeyboardType {
            int UNKNOWN = 0;
            int FALSE = 1;
            int TRUE = 2;
        }
        @ShowImeWithHardKeyboardType
        private int mShowImeWithHardKeyboard = ShowImeWithHardKeyboardType.UNKNOWN;

        private final InputMethodService mService;

        private SettingsObserver(InputMethodService service) {
            super(new Handler(service.getMainLooper()));
            mService = service;
        }

        /**
         * A factory method that internally enforces two-phase initialization to make sure that the
         * object reference will not be escaped until the object is properly constructed.
         *
         * <p>NOTE: Currently {@link SettingsObserver} is accessed only from main thread.  Hence
         * this enforcement of two-phase initialization may be unnecessary at the moment.</p>
         *
         * @param service {@link InputMethodService} that needs to receive the callback.
         * @return {@link SettingsObserver} that is already registered to
         * {@link android.content.ContentResolver}. The caller must call
         * {@link SettingsObserver#unregister()}.
         */
        public static SettingsObserver createAndRegister(InputMethodService service) {
            final SettingsObserver observer = new SettingsObserver(service);
            // The observer is properly constructed. Let's start accepting the event.
            service.getContentResolver().registerContentObserver(
                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD),
                    false, observer);
            return observer;
        }

        void unregister() {
            mService.getContentResolver().unregisterContentObserver(this);
        }

        private boolean shouldShowImeWithHardKeyboard() {
            // Lazily initialize as needed.
            if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {
                mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
                        ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
            }
            switch (mShowImeWithHardKeyboard) {
                case ShowImeWithHardKeyboardType.TRUE:
                    return true;
                case ShowImeWithHardKeyboardType.FALSE:
                    return false;
                default:
                    Log.e(TAG, "Unexpected mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard);
                    return false;
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            final Uri showImeWithHardKeyboardUri =
                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
            if (showImeWithHardKeyboardUri.equals(uri)) {
                mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
                        ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
                mService.updateInputViewShown();
            }
        }

        @Override
        public String toString() {
            return "SettingsObserver{mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard  + "}";
        }
    }
    private SettingsObserver mSettingsObserver;

    /**
     * You can call this to customize the theme used by your IME's window.
     * This theme should typically be one that derives from
@@ -682,6 +781,7 @@ public class InputMethodService extends AbstractInputMethodService {
        super.setTheme(mTheme);
        super.onCreate();
        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
        mSettingsObserver = SettingsObserver.createAndRegister(this);
        // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
        // we continue to use the same size of the inset or update it
        mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
@@ -764,6 +864,10 @@ public class InputMethodService extends AbstractInputMethodService {
            mWindow.getWindow().setWindowAnimations(0);
            mWindow.dismiss();
        }
        if (mSettingsObserver != null) {
            mSettingsObserver.unregister();
            mSettingsObserver = null;
        }
    }

    /**
@@ -1142,14 +1246,21 @@ public class InputMethodService extends AbstractInputMethodService {
    }

    /**
     * Override this to control when the soft input area should be shown to
     * the user.  The default implementation only shows the input view when
     * there is no hard keyboard or the keyboard is hidden.  If you change what
     * this returns, you will need to call {@link #updateInputViewShown()}
     * yourself whenever the returned value may have changed to have it
     * re-evaluated and applied.
     * Override this to control when the soft input area should be shown to the user.  The default
     * implementation returns {@code false} when there is no hard keyboard or the keyboard is hidden
     * unless the user shows an intention to use software keyboard.  If you change what this
     * returns, you will need to call {@link #updateInputViewShown()} yourself whenever the returned
     * value may have changed to have it re-evaluated and applied.
     *
     * <p>When you override this method, it is recommended to call
     * {@code super.onEvaluateInputViewShown()} and return {@code true} when {@code true} is
     * returned.</p>
     */
    @CallSuper
    public boolean onEvaluateInputViewShown() {
        if (mSettingsObserver.shouldShowImeWithHardKeyboard()) {
            return true;
        }
        Configuration config = getResources().getConfiguration();
        return config.keyboard == Configuration.KEYBOARD_NOKEYS
                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
@@ -2483,5 +2594,6 @@ public class InputMethodService extends AbstractInputMethodService {
                + " touchableInsets=" + mTmpInsets.touchableInsets
                + " touchableRegion=" + mTmpInsets.touchableRegion);
        p.println(" mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
        p.println(" mSettingsObserver=" + mSettingsObserver);
    }
}
+1 −25
Original line number Diff line number Diff line
@@ -578,31 +578,23 @@ public class WindowManagerService extends IWindowManager.Stub
    final ArrayList<WindowState> mTmpWindows = new ArrayList<>();

    boolean mHardKeyboardAvailable;
    boolean mShowImeWithHardKeyboard;
    WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
    SettingsObserver mSettingsObserver;

    private final class SettingsObserver extends ContentObserver {
        private final Uri mShowImeWithHardKeyboardUri =
                Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);

        private final Uri mDisplayInversionEnabledUri =
                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);

        public SettingsObserver() {
            super(new Handler());
            ContentResolver resolver = mContext.getContentResolver();
            resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
                    UserHandle.USER_ALL);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (mShowImeWithHardKeyboardUri.equals(uri)) {
                updateShowImeWithHardKeyboard();
            } else if (mDisplayInversionEnabledUri.equals(uri)) {
            if (mDisplayInversionEnabledUri.equals(uri)) {
                updateCircularDisplayMaskIfNeeded();
            }
        }
@@ -946,7 +938,6 @@ public class WindowManagerService extends IWindowManager.Stub
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mSettingsObserver = new SettingsObserver();
        updateShowImeWithHardKeyboard();

        mHoldingScreenWakeLock = mPowerManager.newWakeLock(
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
@@ -7111,9 +7102,6 @@ public class WindowManagerService extends IWindowManager.Stub
            mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
            mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
        }
        if (mShowImeWithHardKeyboard) {
            config.keyboard = Configuration.KEYBOARD_NOKEYS;
        }

        // Let the policy update hidden states.
        config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
@@ -7122,18 +7110,6 @@ public class WindowManagerService extends IWindowManager.Stub
        mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
    }

    public void updateShowImeWithHardKeyboard() {
        synchronized (mWindowMap) {
            final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
                    mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
                    mCurrentUserId) == 1;
            if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) {
                mShowImeWithHardKeyboard = showImeWithHardKeyboard;
                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
            }
        }
    }

    void notifyHardKeyboardStatusChange() {
        final boolean available;
        final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;