OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser; |
| 6 |
| 7 import android.app.Activity; |
| 8 import android.app.AlarmManager; |
| 9 import android.app.PendingIntent; |
| 10 import android.content.Context; |
| 11 import android.content.Intent; |
| 12 import android.os.Handler; |
| 13 import android.os.Looper; |
| 14 import android.os.Process; |
| 15 import android.util.Log; |
| 16 |
| 17 import org.chromium.base.ActivityState; |
| 18 import org.chromium.base.ApplicationStatus; |
| 19 |
| 20 import java.lang.ref.WeakReference; |
| 21 |
| 22 /** |
| 23 * Handles killing and potentially restarting Chrome's main Browser process. No
te that this class |
| 24 * relies on main Chrome activities to properly call {@link Activity#finish()} o
n themselves so that |
| 25 * it will be notified that all {@link Activity}s under this {@link Application}
have been |
| 26 * destroyed. |
| 27 */ |
| 28 class ChromeLifetimeController implements ApplicationLifetime.Observer, |
| 29 ApplicationStatus.ActivityStateListener { |
| 30 private static final String TAG = "ChromeLifetimeController"; |
| 31 |
| 32 private final Context mContext; |
| 33 private boolean mRestartChromeOnDestroy; |
| 34 private int mRemainingActivitiesCount = 0; |
| 35 |
| 36 /** |
| 37 * Creates a {@link ChromeLifetimeController} instance. |
| 38 * @param context A {@link Context} instance. The application context will
be saved from this |
| 39 * one. |
| 40 */ |
| 41 public ChromeLifetimeController(Context context) { |
| 42 mContext = context.getApplicationContext(); |
| 43 ApplicationLifetime.addObserver(this); |
| 44 } |
| 45 |
| 46 @Override |
| 47 public void onTerminate(boolean restart) { |
| 48 mRestartChromeOnDestroy = restart; |
| 49 |
| 50 // We've called terminate twice, just wait for the first call to take ef
fect. |
| 51 if (mRemainingActivitiesCount > 0) { |
| 52 Log.w(TAG, "onTerminate called twice"); |
| 53 return; |
| 54 } |
| 55 |
| 56 for (WeakReference<Activity> weakActivity : ApplicationStatus.getRunning
Activities()) { |
| 57 Activity activity = weakActivity.get(); |
| 58 if (activity != null) { |
| 59 ApplicationStatus.registerStateListenerForActivity(this, activit
y); |
| 60 mRemainingActivitiesCount++; |
| 61 activity.finish(); |
| 62 } |
| 63 } |
| 64 } |
| 65 |
| 66 |
| 67 @Override |
| 68 public void onActivityStateChange(Activity activity, int newState) { |
| 69 assert mRemainingActivitiesCount > 0; |
| 70 if (newState == ActivityState.DESTROYED) { |
| 71 mRemainingActivitiesCount--; |
| 72 if (mRemainingActivitiesCount == 0) { |
| 73 destroyProcess(); |
| 74 } |
| 75 } |
| 76 |
| 77 } |
| 78 |
| 79 private void destroyProcess() { |
| 80 Handler handler = new Handler(Looper.getMainLooper()); |
| 81 handler.post(new Runnable() { |
| 82 @Override |
| 83 public void run() { |
| 84 if (mRestartChromeOnDestroy) scheduleRestart(mContext); |
| 85 |
| 86 Log.w(TAG, "Forcefully killing process..."); |
| 87 Process.killProcess(Process.myPid()); |
| 88 |
| 89 mRestartChromeOnDestroy = false; |
| 90 } |
| 91 }); |
| 92 } |
| 93 |
| 94 private static void scheduleRestart(Context context) { |
| 95 Intent intent = new Intent(); |
| 96 intent.setPackage(context.getPackageName()); |
| 97 intent.setAction(Intent.ACTION_MAIN); |
| 98 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| 99 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, inte
nt, |
| 100 PendingIntent.FLAG_ONE_SHOT); |
| 101 if (pendingIntent != null) { |
| 102 AlarmManager am = (AlarmManager) context.getSystemService(Context.AL
ARM_SERVICE); |
| 103 am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingI
ntent); |
| 104 } |
| 105 } |
| 106 } |
OLD | NEW |