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