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