1d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian/* 2d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Copyright (C) 2017 The Android Open Source Project 3d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 4d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * This file is derived in part from code issued under the following license. 5d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 6d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 7d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * you may not use this file except in compliance with the License. 8d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * You may obtain a copy of the License at 9d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 10d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 11d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 12d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Unless required by applicable law or agreed to in writing, software 13d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 14d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * See the License for the specific language governing permissions and 16d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * limitations under the License. 17d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 18d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 19d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianpackage com.android.dialer.oem; 20d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 21d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.ActivityNotFoundException; 22d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.Context; 23d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.Intent; 24d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.pm.ResolveInfo; 25d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport com.android.dialer.common.LogUtil; 26d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.regex.Pattern; 27d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 28d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian/** 29d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Util class to handle special char sequence and launch corresponding intent based the sequence. 30d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 31d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianpublic class MotorolaHiddenMenuKeySequence { 32d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String EXTRA_HIDDEN_MENU_CODE = "HiddenMenuCode"; 33d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static MotorolaHiddenMenuKeySequence instance = null; 34d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 35d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static String[] hiddenKeySequenceArray = null; 36d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static String[] hiddenKeySequenceIntentArray = null; 37d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static String[] hiddenKeyPatternArray = null; 38d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static String[] hiddenKeyPatternIntentArray = null; 39d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static boolean featureHiddenMenuEnabled = false; 40d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 41d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 42d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Handle input char sequence. 43d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 44d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param context context 45d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param input input sequence 46d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @return true if the input matches any pattern 47d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 48d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian static boolean handleCharSequence(Context context, String input) { 49d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian getInstance(context); 50d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (!featureHiddenMenuEnabled) { 51d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 52d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 53d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return handleKeySequence(context, input) || handleKeyPattern(context, input); 54d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 55d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 56d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 57d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Public interface to return the Singleton instance 58d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 59d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param context the Context 60d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @return the MotorolaHiddenMenuKeySequence singleton instance 61d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 62d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static synchronized MotorolaHiddenMenuKeySequence getInstance(Context context) { 63d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (null == instance) { 64d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian instance = new MotorolaHiddenMenuKeySequence(context); 65d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 66d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return instance; 67d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 68d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 69d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private MotorolaHiddenMenuKeySequence(Context context) { 70d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian featureHiddenMenuEnabled = 719050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian MotorolaUtils.isSpnMatched(context) 729050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian && context.getResources().getBoolean(R.bool.motorola_feature_hidden_menu); 73d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian // In case we do have a SPN from resource we need to match from service; otherwise we are 74d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian // free to go 75d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (featureHiddenMenuEnabled) { 76d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 77d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeySequenceArray = 78d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian context.getResources().getStringArray(R.array.motorola_hidden_menu_key_sequence); 79d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeySequenceIntentArray = 80d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian context.getResources().getStringArray(R.array.motorola_hidden_menu_key_sequence_intents); 81d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeyPatternArray = 82d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian context.getResources().getStringArray(R.array.motorola_hidden_menu_key_pattern); 83d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeyPatternIntentArray = 84d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian context.getResources().getStringArray(R.array.motorola_hidden_menu_key_pattern_intents); 85d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 86d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (hiddenKeySequenceArray.length != hiddenKeySequenceIntentArray.length 87d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian || hiddenKeyPatternArray.length != hiddenKeyPatternIntentArray.length 88d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian || (hiddenKeySequenceArray.length == 0 && hiddenKeyPatternArray.length == 0)) { 89d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian LogUtil.e( 90d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian "MotorolaHiddenMenuKeySequence", 91d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian "the key sequence array is not matching, turn off feature." 92d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + "key sequence: %d != %d, key pattern %d != %d", 93d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeySequenceArray.length, 94d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeySequenceIntentArray.length, 95d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeyPatternArray.length, 96d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian hiddenKeyPatternIntentArray.length); 97d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian featureHiddenMenuEnabled = false; 98d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 99d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 100d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 101d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 102d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static boolean handleKeyPattern(Context context, String input) { 103d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian int len = input.length(); 104d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (len <= 3 || hiddenKeyPatternArray == null || hiddenKeyPatternIntentArray == null) { 105d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 106d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 107d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 108d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian for (int i = 0; i < hiddenKeyPatternArray.length; i++) { 109d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if ((Pattern.compile(hiddenKeyPatternArray[i])).matcher(input).matches()) { 110d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return sendIntent(context, input, hiddenKeyPatternIntentArray[i]); 111d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 112d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 113d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 114d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 115d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 116d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static boolean handleKeySequence(Context context, String input) { 117d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian int len = input.length(); 118d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (len <= 3 || hiddenKeySequenceArray == null || hiddenKeySequenceIntentArray == null) { 119d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 120d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 121d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 122d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian for (int i = 0; i < hiddenKeySequenceArray.length; i++) { 123d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (hiddenKeySequenceArray[i].equals(input)) { 124d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return sendIntent(context, input, hiddenKeySequenceIntentArray[i]); 125d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 126d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 127d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 128d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 129d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 130d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static boolean sendIntent( 131d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian final Context context, final String input, final String action) { 132d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian LogUtil.d("MotorolaHiddenMenuKeySequence.sendIntent", "input: %s", input); 133d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian try { 134d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Intent intent = new Intent(action); 135d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 136d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian intent.putExtra(EXTRA_HIDDEN_MENU_CODE, input); 137d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 138d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 0); 139d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 140d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (resolveInfo != null 141d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian && resolveInfo.activityInfo != null 142d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian && resolveInfo.activityInfo.enabled) { 143d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian context.startActivity(intent); 144d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return true; 145d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 146d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian LogUtil.w("MotorolaHiddenMenuKeySequence.sendIntent", "not able to resolve the intent"); 147d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 148d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } catch (ActivityNotFoundException e) { 149d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian LogUtil.e( 150d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian "MotorolaHiddenMenuKeySequence.sendIntent", "handleHiddenMenu Key Pattern Exception", e); 151d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 152d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return false; 153d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 154d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian} 155