1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.latin; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.os.Process; 23 import android.util.Log; 24 import android.view.inputmethod.InputMethodManager; 25 import android.view.inputmethod.InputMethodSubtype; 26 27 import com.android.inputmethod.compat.IntentCompatUtils; 28 import com.android.inputmethod.keyboard.KeyboardLayoutSet; 29 import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager; 30 import com.android.inputmethod.latin.utils.UncachedInputMethodManagerUtils; 31 32 /** 33 * This class detects the {@link Intent#ACTION_MY_PACKAGE_REPLACED} broadcast intent when this IME 34 * package has been replaced by a newer version of the same package. This class also detects 35 * {@link Intent#ACTION_BOOT_COMPLETED} and {@link Intent#ACTION_USER_INITIALIZE} broadcast intent. 36 * 37 * If this IME has already been installed in the system image and a new version of this IME has 38 * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is received by this receiver and it 39 * will hide the setup wizard's icon. 40 * 41 * If this IME has already been installed in the data partition and a new version of this IME has 42 * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is received by this receiver but it 43 * will not hide the setup wizard's icon, and the icon will appear on the launcher. 44 * 45 * If this IME hasn't been installed yet and has been newly installed, no 46 * {@link Intent#ACTION_MY_PACKAGE_REPLACED} will be sent and the setup wizard's icon will appear 47 * on the launcher. 48 * 49 * When the device has been booted, {@link Intent#ACTION_BOOT_COMPLETED} is received by this 50 * receiver and it checks whether the setup wizard's icon should be appeared or not on the launcher 51 * depending on which partition this IME is installed. 52 * 53 * When a multiuser account has been created, {@link Intent#ACTION_USER_INITIALIZE} is received 54 * by this receiver and it checks the whether the setup wizard's icon should be appeared or not on 55 * the launcher depending on which partition this IME is installed. 56 * 57 * When the system locale has been changed, {@link Intent#ACTION_LOCALE_CHANGED} is received by 58 * this receiver and the {@link KeyboardLayoutSet}'s cache is cleared. 59 */ 60 public final class SystemBroadcastReceiver extends BroadcastReceiver { 61 private static final String TAG = SystemBroadcastReceiver.class.getSimpleName(); 62 63 @Override 64 public void onReceive(final Context context, final Intent intent) { 65 final String intentAction = intent.getAction(); 66 if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(intentAction)) { 67 Log.i(TAG, "Package has been replaced: " + context.getPackageName()); 68 // Need to restore additional subtypes because system always clears additional 69 // subtypes when the package is replaced. 70 RichInputMethodManager.init(context); 71 final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); 72 final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(context); 73 richImm.setAdditionalInputMethodSubtypes(additionalSubtypes); 74 LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context); 75 } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) { 76 Log.i(TAG, "Boot has been completed"); 77 LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context); 78 } else if (IntentCompatUtils.is_ACTION_USER_INITIALIZE(intentAction)) { 79 Log.i(TAG, "User initialize"); 80 LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context); 81 } else if (Intent.ACTION_LOCALE_CHANGED.equals(intentAction)) { 82 Log.i(TAG, "System locale changed"); 83 KeyboardLayoutSet.onSystemLocaleChanged(); 84 } 85 86 // The process that hosts this broadcast receiver is invoked and remains alive even after 87 // 1) the package has been re-installed, 2) the device has just booted, 88 // 3) a new user has been created. 89 // There is no good reason to keep the process alive if this IME isn't a current IME. 90 final InputMethodManager imm = 91 (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); 92 // Called to check whether this IME has been triggered by the current user or not 93 final boolean isInputMethodManagerValidForUserOfThisProcess = 94 !imm.getInputMethodList().isEmpty(); 95 final boolean isCurrentImeOfCurrentUser = isInputMethodManagerValidForUserOfThisProcess 96 && UncachedInputMethodManagerUtils.isThisImeCurrent(context, imm); 97 if (!isCurrentImeOfCurrentUser) { 98 final int myPid = Process.myPid(); 99 Log.i(TAG, "Killing my process: pid=" + myPid); 100 Process.killProcess(myPid); 101 } 102 } 103 } 104