<commit_before>/**
 * Copyright (C) 2016 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 android.support.v13.view.inputmethod;

import android.content.ClipDescription;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.BuildCompat;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;

/**
 * Helper for accessing features in {@link InputConnection} introduced after API level 13 in a
 * backwards compatible fashion.
 */
public final class InputConnectionCompat {

    private interface InputConnectionCompatImpl {
        boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags, @Nullable Bundle opts);

        @NonNull
        InputConnection createWrapper(@NonNull InputConnection ic,
                @NonNull EditorInfo editorInfo, @NonNull OnCommitContentListener callback);
    }

    static final class BaseInputContentInfoCompatImpl implements InputConnectionCompatImpl {

        private static String COMMIT_CONTENT_ACTION =
                "android.support.v13.view.inputmethod.InputConnectionCompat.COMMIT_CONTENT";
        private static String COMMIT_CONTENT_CONTENT_URI_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_URI";
        private static String COMMIT_CONTENT_DESCRIPTION_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_DESCRIPTION";
        private static String COMMIT_CONTENT_LINK_URI_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_LINK_URI";
        private static String COMMIT_CONTENT_OPTS_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_OPTS";
        private static String COMMIT_CONTENT_FLAGS_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_FLAGS";
        private static String COMMIT_CONTENT_RESULT_RECEIVER =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_RESULT_RECEIVER";

        @Override
        public boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags,
                @Nullable Bundle opts) {
            final Bundle params = new Bundle();
            params.putParcelable(COMMIT_CONTENT_CONTENT_URI_KEY, inputContentInfo.getContentUri());
            params.putParcelable(COMMIT_CONTENT_DESCRIPTION_KEY, inputContentInfo.getDescription());
            params.putParcelable(COMMIT_CONTENT_LINK_URI_KEY, inputContentInfo.getLinkUri());
            params.putInt(COMMIT_CONTENT_FLAGS_KEY, flags);
            params.putParcelable(COMMIT_CONTENT_OPTS_KEY, opts);
            // TODO: Support COMMIT_CONTENT_RESULT_RECEIVER.
            return inputConnection.performPrivateCommand(COMMIT_CONTENT_ACTION, params);
        }

        @NonNull
        @Override
        public InputConnection createWrapper(@NonNull InputConnection ic,
                @NonNull EditorInfo editorInfo,
                @NonNull OnCommitContentListener onCommitContentListener) {
            String[] contentMimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);
            if (contentMimeTypes.length == 0) {
                return ic;
            }
            final OnCommitContentListener listener = onCommitContentListener;
            return new InputConnectionWrapper(ic, false /* mutable */) {
                @Override
                public boolean performPrivateCommand(String action, Bundle data) {
                    if (BaseInputContentInfoCompatImpl.handlePerformPrivateCommand(action, data,
                            listener)) {
                        return true;
                    }
                    return super.performPrivateCommand(action, data);
                }
            };
        }

        static boolean handlePerformPrivateCommand(
                @Nullable String action,
                @NonNull Bundle data,
                @NonNull OnCommitContentListener onCommitContentListener) {
            if (!TextUtils.equals(COMMIT_CONTENT_ACTION, action)) {
                return false;
            }
            if (data == null) {
                return false;
            }
            ResultReceiver resultReceiver = null;
            boolean result = false;
            try {
                resultReceiver = data.getParcelable(COMMIT_CONTENT_RESULT_RECEIVER);
                final Uri contentUri = data.getParcelable(COMMIT_CONTENT_CONTENT_URI_KEY);
                final ClipDescription description = data.getParcelable(
                        COMMIT_CONTENT_DESCRIPTION_KEY);
                final Uri linkUri = data.getParcelable(COMMIT_CONTENT_LINK_URI_KEY);
                final int flags = data.getParcelable(COMMIT_CONTENT_FLAGS_KEY);
                final Bundle opts = data.getParcelable(COMMIT_CONTENT_OPTS_KEY);
                final InputContentInfoCompat inputContentInfo =
                        new InputContentInfoCompat(contentUri, description, linkUri);
                result = onCommitContentListener.onCommitContent(inputContentInfo, flags, opts);
            } finally {
                if (resultReceiver != null) {
                    resultReceiver.send(result ? 1 : 0, null);
                }
            }
            return result;
        }
    }

    private final static class Api25InputContentInfoCompatImpl
            implements InputConnectionCompatImpl {
        @Override
        public boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags,
                @Nullable Bundle opts) {<commit_msg>Fix a type mismatch in COMMIT_CONTENT_FLAGS_KEY<commit_after>/**
 * Copyright (C) 2016 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 android.support.v13.view.inputmethod;

import android.content.ClipDescription;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.BuildCompat;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;

/**
 * Helper for accessing features in {@link InputConnection} introduced after API level 13 in a
 * backwards compatible fashion.
 */
public final class InputConnectionCompat {

    private interface InputConnectionCompatImpl {
        boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags, @Nullable Bundle opts);

        @NonNull
        InputConnection createWrapper(@NonNull InputConnection ic,
                @NonNull EditorInfo editorInfo, @NonNull OnCommitContentListener callback);
    }

    static final class BaseInputContentInfoCompatImpl implements InputConnectionCompatImpl {

        private static String COMMIT_CONTENT_ACTION =
                "android.support.v13.view.inputmethod.InputConnectionCompat.COMMIT_CONTENT";
        private static String COMMIT_CONTENT_CONTENT_URI_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_URI";
        private static String COMMIT_CONTENT_DESCRIPTION_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_DESCRIPTION";
        private static String COMMIT_CONTENT_LINK_URI_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_LINK_URI";
        private static String COMMIT_CONTENT_OPTS_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_OPTS";
        private static String COMMIT_CONTENT_FLAGS_KEY =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_FLAGS";
        private static String COMMIT_CONTENT_RESULT_RECEIVER =
                "android.support.v13.view.inputmethod.InputConnectionCompat.CONTENT_RESULT_RECEIVER";

        @Override
        public boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags,
                @Nullable Bundle opts) {
            final Bundle params = new Bundle();
            params.putParcelable(COMMIT_CONTENT_CONTENT_URI_KEY, inputContentInfo.getContentUri());
            params.putParcelable(COMMIT_CONTENT_DESCRIPTION_KEY, inputContentInfo.getDescription());
            params.putParcelable(COMMIT_CONTENT_LINK_URI_KEY, inputContentInfo.getLinkUri());
            params.putInt(COMMIT_CONTENT_FLAGS_KEY, flags);
            params.putParcelable(COMMIT_CONTENT_OPTS_KEY, opts);
            // TODO: Support COMMIT_CONTENT_RESULT_RECEIVER.
            return inputConnection.performPrivateCommand(COMMIT_CONTENT_ACTION, params);
        }

        @NonNull
        @Override
        public InputConnection createWrapper(@NonNull InputConnection ic,
                @NonNull EditorInfo editorInfo,
                @NonNull OnCommitContentListener onCommitContentListener) {
            String[] contentMimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);
            if (contentMimeTypes.length == 0) {
                return ic;
            }
            final OnCommitContentListener listener = onCommitContentListener;
            return new InputConnectionWrapper(ic, false /* mutable */) {
                @Override
                public boolean performPrivateCommand(String action, Bundle data) {
                    if (BaseInputContentInfoCompatImpl.handlePerformPrivateCommand(action, data,
                            listener)) {
                        return true;
                    }
                    return super.performPrivateCommand(action, data);
                }
            };
        }

        static boolean handlePerformPrivateCommand(
                @Nullable String action,
                @NonNull Bundle data,
                @NonNull OnCommitContentListener onCommitContentListener) {
            if (!TextUtils.equals(COMMIT_CONTENT_ACTION, action)) {
                return false;
            }
            if (data == null) {
                return false;
            }
            ResultReceiver resultReceiver = null;
            boolean result = false;
            try {
                resultReceiver = data.getParcelable(COMMIT_CONTENT_RESULT_RECEIVER);
                final Uri contentUri = data.getParcelable(COMMIT_CONTENT_CONTENT_URI_KEY);
                final ClipDescription description = data.getParcelable(
                        COMMIT_CONTENT_DESCRIPTION_KEY);
                final Uri linkUri = data.getParcelable(COMMIT_CONTENT_LINK_URI_KEY);
                final int flags = data.getInt(COMMIT_CONTENT_FLAGS_KEY);
                final Bundle opts = data.getParcelable(COMMIT_CONTENT_OPTS_KEY);
                final InputContentInfoCompat inputContentInfo =
                        new InputContentInfoCompat(contentUri, description, linkUri);
                result = onCommitContentListener.onCommitContent(inputContentInfo, flags, opts);
            } finally {
                if (resultReceiver != null) {
                    resultReceiver.send(result ? 1 : 0, null);
                }
            }
            return result;
        }
    }

    private final static class Api25InputContentInfoCompatImpl
            implements InputConnectionCompatImpl {
        @Override
        public boolean commitContent(@NonNull InputConnection inputConnection,
                @NonNull InputContentInfoCompat inputContentInfo, int flags,
                @Nullable Bundle opts) {
{'fraction_non_alphanumeric': 0.06322846042507808, 'fraction_numerical': 0.0048754475508493945, 'mean_word_length': 2.612548156301596, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2563206', 'n_tokens_mistral': 3228, 'n_tokens_neox': 3125, 'n_words': 753}