1 /* 2 * Copyright (C) 2015 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.messaging.util; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.Debug; 22 import android.os.PowerManager; 23 import android.os.Process; 24 25 import com.google.common.annotations.VisibleForTesting; 26 27 /** 28 * Helper class used to manage wakelock state 29 */ 30 public class WakeLockHelper { 31 private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; 32 private static final boolean VERBOSE = false; 33 34 @VisibleForTesting 35 public static final String EXTRA_CALLING_PID = "pid"; 36 37 private final Object mLock = new Object(); 38 private final String mWakeLockId; 39 private final int mMyPid; 40 41 private PowerManager.WakeLock mWakeLock; 42 43 public WakeLockHelper(final String wakeLockId) { 44 mWakeLockId = wakeLockId; 45 mMyPid = Process.myPid(); 46 } 47 48 /** 49 * Acquire the wakelock 50 */ 51 public void acquire(final Context context, final Intent intent, final int opcode) { 52 synchronized (mLock) { 53 if (mWakeLock == null) { 54 if (VERBOSE) { 55 LogUtil.v(TAG, "initializing wakelock"); 56 } 57 final PowerManager pm = (PowerManager) 58 context.getSystemService(Context.POWER_SERVICE); 59 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mWakeLockId); 60 } 61 } 62 if (VERBOSE) { 63 LogUtil.v(TAG, "acquiring " + mWakeLockId + " for opcode " + opcode); 64 } 65 mWakeLock.acquire(); 66 intent.putExtra(EXTRA_CALLING_PID, mMyPid); 67 } 68 69 /** 70 * Check if wakelock held by this process 71 */ 72 public boolean isHeld(final Intent intent) { 73 final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1)); 74 return (respectWakeLock && mWakeLock.isHeld()); 75 } 76 77 /** 78 * Ensure that wakelock is held by this process 79 */ 80 public boolean ensure(final Intent intent, final int opcode) { 81 final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1)); 82 if (VERBOSE) { 83 LogUtil.v(TAG, "WakeLockHelper.ensure Intent " + intent + " " 84 + intent.getAction() + " opcode: " + opcode 85 + " respectWakeLock " + respectWakeLock); 86 } 87 88 if (respectWakeLock) { 89 final boolean isHeld = (respectWakeLock && isHeld(intent)); 90 if (!isHeld) { 91 LogUtil.e(TAG, "WakeLockHelper.ensure called " + intent + " " + intent.getAction() 92 + " opcode: " + opcode + " sWakeLock: " + mWakeLock + " isHeld: " 93 + ((mWakeLock == null) ? "(null)" : mWakeLock.isHeld())); 94 if (!Debug.isDebuggerConnected()) { 95 Assert.fail("WakeLock dropped prior to service starting"); 96 } 97 } 98 return true; 99 } 100 return false; 101 } 102 103 /** 104 * Release wakelock (if it is held by this process) 105 */ 106 public void release(final Intent intent, final int opcode) { 107 final boolean respectWakeLock = (mMyPid == intent.getIntExtra(EXTRA_CALLING_PID, -1)); 108 if (respectWakeLock) { 109 try { 110 mWakeLock.release(); 111 } catch (final RuntimeException ex) { 112 LogUtil.e(TAG, "KeepAliveService.onHandleIntent exit crash " + intent + " " 113 + intent.getAction() + " opcode: " + opcode + " sWakeLock: " + mWakeLock 114 + " isHeld: " + ((mWakeLock == null) ? "(null)" : mWakeLock.isHeld())); 115 if (!Debug.isDebuggerConnected()) { 116 Assert.fail("WakeLock no longer held at end of handler"); 117 } 118 } 119 } 120 } 121 } 122