1b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha/*
2b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * Copyright (C) 2014 The Android Open Source Project
3b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha *
4b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * Licensed under the Apache License, Version 2.0 (the "License");
5b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * you may not use this file except in compliance with the License.
6b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * You may obtain a copy of the License at
7b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha *
8b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha *      http://www.apache.org/licenses/LICENSE-2.0
9b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha *
10b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * Unless required by applicable law or agreed to in writing, software
11b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * distributed under the License is distributed on an "AS IS" BASIS,
12b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * See the License for the specific language governing permissions and
14b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * limitations under the License.
15b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha */
16b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
17b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthapackage com.android.test.voiceenrollment;
18b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
19b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.annotation.Nullable;
20b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.content.Context;
21b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
22b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger;
23b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger.Keyphrase;
24b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
25b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.os.RemoteException;
26b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.os.ServiceManager;
27b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.service.voice.AlwaysOnHotwordDetector;
28b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport android.util.Log;
29b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
30b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthaimport com.android.internal.app.IVoiceInteractionManagerService;
31b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
32b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha/**
33b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha * Utility class for the enrollment operations like enroll;re-enroll & un-enroll.
34b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha */
35b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddharthapublic class EnrollmentUtil {
36b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    private static final String TAG = "TestEnrollmentUtil";
37b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
38b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
39b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Activity Action: Show activity for managing the keyphrases for hotword detection.
40b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * This needs to be defined by an activity that supports enrolling users for hotword/keyphrase
41b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * detection.
42b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
43b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final String ACTION_MANAGE_VOICE_KEYPHRASES =
44b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            KeyphraseEnrollmentInfo.ACTION_MANAGE_VOICE_KEYPHRASES;
45b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
46b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
47b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Intent extra: The intent extra for the specific manage action that needs to be performed.
48b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Possible values are {@link AlwaysOnHotwordDetector#MANAGE_ACTION_ENROLL},
49b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * {@link AlwaysOnHotwordDetector#MANAGE_ACTION_RE_ENROLL}
50b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * or {@link AlwaysOnHotwordDetector#MANAGE_ACTION_UN_ENROLL}.
51b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
52b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final String EXTRA_VOICE_KEYPHRASE_ACTION =
53b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            KeyphraseEnrollmentInfo.EXTRA_VOICE_KEYPHRASE_ACTION;
54b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
55b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
56b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Intent extra: The hint text to be shown on the voice keyphrase management UI.
57b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
58b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final String EXTRA_VOICE_KEYPHRASE_HINT_TEXT =
59b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            KeyphraseEnrollmentInfo.EXTRA_VOICE_KEYPHRASE_HINT_TEXT;
60b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
61b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Intent extra: The voice locale to use while managing the keyphrase.
62b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
63b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final String EXTRA_VOICE_KEYPHRASE_LOCALE =
64b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            KeyphraseEnrollmentInfo.EXTRA_VOICE_KEYPHRASE_LOCALE;
65b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
66b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /** Simple recognition of the key phrase */
67b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final int RECOGNITION_MODE_VOICE_TRIGGER =
68b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER;
69b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /** Trigger only if one user is identified */
70b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public static final int RECOGNITION_MODE_USER_IDENTIFICATION =
71b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
72b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
73b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    private final IVoiceInteractionManagerService mModelManagementService;
74b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
75b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public EnrollmentUtil() {
76b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        mModelManagementService = IVoiceInteractionManagerService.Stub.asInterface(
77b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
78b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    }
79b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
80b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
81b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Adds/Updates a sound model.
82b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * The sound model must contain a valid UUID,
83b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * exactly 1 keyphrase,
84b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * and users for which the keyphrase is valid - typically the current user.
85b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     *
86b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @param soundModel The sound model to add/update.
87b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @return {@code true} if the call succeeds, {@code false} otherwise.
88b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
89b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public boolean addOrUpdateSoundModel(KeyphraseSoundModel soundModel) {
90b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (!verifyKeyphraseSoundModel(soundModel)) {
91b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
92b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
93b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
94b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        int status = SoundTrigger.STATUS_ERROR;
95b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        try {
96b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            status = mModelManagementService.updateKeyphraseSoundModel(soundModel);
97b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        } catch (RemoteException e) {
98b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "RemoteException in updateKeyphraseSoundModel", e);
99b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
100b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        return status == SoundTrigger.STATUS_OK;
101b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    }
102b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
103b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
104b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Gets the sound model for the given keyphrase, null if none exists.
105b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * This should be used for re-enrollment purposes.
106b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * If a sound model for a given keyphrase exists, and it needs to be updated,
107b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * it should be obtained using this method, updated and then passed in to
108b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * {@link #addOrUpdateSoundModel(KeyphraseSoundModel)} without changing the IDs.
109b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     *
110b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @param keyphraseId The keyphrase ID to look-up the sound model for.
111b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @param bcp47Locale The locale for with to look up the sound model for.
112b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @return The sound model if one was found, null otherwise.
113b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
114b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    @Nullable
115b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public KeyphraseSoundModel getSoundModel(int keyphraseId, String bcp47Locale) {
116b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphraseId <= 0) {
117b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Keyphrase must have a valid ID");
118b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return null;
119b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
120b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
121b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        KeyphraseSoundModel model = null;
122b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        try {
123b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            model = mModelManagementService.getKeyphraseSoundModel(keyphraseId, bcp47Locale);
124b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        } catch (RemoteException e) {
125b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "RemoteException in updateKeyphraseSoundModel");
126b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
127b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
128b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (model == null) {
129b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.w(TAG, "No models present for the gien keyphrase ID");
130b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return null;
131b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        } else {
132b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return model;
133b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
134b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    }
135b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
136b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    /**
137b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * Deletes the sound model for the given keyphrase id.
138b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     *
139b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @param keyphraseId The keyphrase ID to look-up the sound model for.
140b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     * @return {@code true} if the call succeeds, {@code false} otherwise.
141b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha     */
142b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    @Nullable
143b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    public boolean deleteSoundModel(int keyphraseId, String bcp47Locale) {
144b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphraseId <= 0) {
145b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Keyphrase must have a valid ID");
146b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
147b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
148b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
149b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        int status = SoundTrigger.STATUS_ERROR;
150b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        try {
151b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            status = mModelManagementService.deleteKeyphraseSoundModel(keyphraseId, bcp47Locale);
152b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        } catch (RemoteException e) {
153b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "RemoteException in updateKeyphraseSoundModel");
154b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
155b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        return status == SoundTrigger.STATUS_OK;
156b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    }
157b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha
158b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    private boolean verifyKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
159b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (soundModel == null) {
160b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "KeyphraseSoundModel must be non-null");
161b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
162b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
163b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (soundModel.uuid == null) {
164b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "KeyphraseSoundModel must have a UUID");
165b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
166b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
167b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (soundModel.data == null) {
168b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "KeyphraseSoundModel must have data");
169b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
170b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
171b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (soundModel.keyphrases == null || soundModel.keyphrases.length != 1) {
172b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Keyphrase must be exactly 1");
173b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
174b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
175b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        Keyphrase keyphrase = soundModel.keyphrases[0];
176b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphrase.id <= 0) {
177b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Keyphrase must have a valid ID");
178b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
179b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
180b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphrase.recognitionModes < 0) {
181b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Recognition modes must be valid");
182b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
183b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
184b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphrase.locale == null) {
185b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Locale must not be null");
186b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
187b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
188b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphrase.text == null) {
189b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Text must not be null");
190b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
191b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
192b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        if (keyphrase.users == null || keyphrase.users.length == 0) {
193b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            Log.e(TAG, "Keyphrase must have valid user(s)");
194b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha            return false;
195b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        }
196b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha        return true;
197b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha    }
198b585ac5b5e672c11c80a01eb42a0d3ebd495f21bSandeep Siddhartha}
199