am 8485098f: Merge "Fixed a leak in GeofenceHardwareImpl.java." into lmp-mr1-dev

* commit '8485098fa22a61f845cb2abbc5bc856b15835a9e':
  Fixed a leak in GeofenceHardwareImpl.java.
This commit is contained in:
Zhentao Sun
2014-12-04 22:58:02 +00:00
committed by Android Git Automerger

View File

@@ -23,6 +23,7 @@ import android.location.IGpsGeofenceHardware;
import android.location.Location;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -30,6 +31,7 @@ import android.util.Log;
import android.util.SparseArray;
import java.util.ArrayList;
import java.util.Iterator;
/**
* This class manages the geofences which are handled by hardware.
@@ -558,8 +560,34 @@ public final class GeofenceHardwareImpl {
try {
callback.onGeofenceRemove(geofenceId, msg.arg2);
} catch (RemoteException e) {}
IBinder callbackBinder = callback.asBinder();
boolean callbackInUse = false;
synchronized (mGeofences) {
mGeofences.remove(geofenceId);
// Check if the underlying binder is still useful for other geofences,
// if no, unlink the DeathRecipient to avoid memory leak.
for (int i = 0; i < mGeofences.size(); i++) {
if (mGeofences.valueAt(i).asBinder() == callbackBinder) {
callbackInUse = true;
break;
}
}
}
// Remove the reaper associated with this binder.
if (!callbackInUse) {
for (Iterator<Reaper> iterator = mReapers.iterator();
iterator.hasNext();) {
Reaper reaper = iterator.next();
if (reaper.mCallback != null &&
reaper.mCallback.asBinder() == callbackBinder) {
iterator.remove();
reaper.unlinkToDeath();
if (DEBUG) Log.d(TAG, String.format("Removed reaper %s " +
"because binder %s is no longer needed.",
reaper, callbackBinder));
}
}
}
}
releaseWakeLock();
@@ -803,8 +831,9 @@ public final class GeofenceHardwareImpl {
@Override
public int hashCode() {
int result = 17;
result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
result = 31 * result + (mMonitorCallback != null ? mMonitorCallback.hashCode() : 0);
result = 31 * result + (mCallback != null ? mCallback.asBinder().hashCode() : 0);
result = 31 * result + (mMonitorCallback != null
? mMonitorCallback.asBinder().hashCode() : 0);
result = 31 * result + mMonitoringType;
return result;
}
@@ -815,9 +844,38 @@ public final class GeofenceHardwareImpl {
if (obj == this) return true;
Reaper rhs = (Reaper) obj;
return rhs.mCallback == mCallback && rhs.mMonitorCallback == mMonitorCallback &&
return binderEquals(rhs.mCallback, mCallback) &&
binderEquals(rhs.mMonitorCallback, mMonitorCallback) &&
rhs.mMonitoringType == mMonitoringType;
}
/**
* Compares the underlying Binder of the given two IInterface objects and returns true if
* they equals. null values are accepted.
*/
private boolean binderEquals(IInterface left, IInterface right) {
if (left == null) {
return right == null;
} else {
return right == null ? false : left.asBinder() == right.asBinder();
}
}
/**
* Unlinks this DeathRecipient.
*/
private boolean unlinkToDeath() {
if (mMonitorCallback != null) {
return mMonitorCallback.asBinder().unlinkToDeath(this, 0);
} else if (mCallback != null) {
return mCallback.asBinder().unlinkToDeath(this, 0);
}
return true;
}
private boolean callbackEquals(IGeofenceHardwareCallback cb) {
return mCallback != null && mCallback.asBinder() == cb.asBinder();
}
}
int getAllowedResolutionLevel(int pid, int uid) {