diff --git a/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java b/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java
index a8e4b89e895a2c3cb26ab9a5f406bfe70db05924..11b5dbc172dc929817275c4559c99bf18a7a3c67 100644
--- a/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java
+++ b/ring-android/app/src/main/java/cx/ring/services/LocationSharingService.java
@@ -2,6 +2,7 @@
  *  Copyright (C) 2004-2020 Savoir-faire Linux Inc.
  *
  *  Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+ *  Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -44,6 +45,7 @@ import androidx.annotation.NonNull;
 import androidx.core.app.ActivityCompat;
 import androidx.core.app.NotificationCompat;
 
+import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.util.Date;
@@ -192,6 +194,7 @@ public class LocationSharingService extends Service implements LocationListener
                         .throttleLatest(10, TimeUnit.SECONDS)
                         .map(location -> {
                             JSONObject out = new JSONObject();
+                            out.put("type", AccountService.Location.Type.position.toString());
                             out.put("lat", location.getLatitude());
                             out.put("long", location.getLongitude());
                             out.put("alt", location.getAltitude());
@@ -220,9 +223,23 @@ public class LocationSharingService extends Service implements LocationListener
         else if (ACTION_STOP.equals(action)) {
             if (path == null)
                 contactLocationShare.clear();
-            else
+            else {
                 contactLocationShare.remove(path);
 
+                JSONObject jsonObject = new JSONObject();
+                try {
+                    jsonObject.put("type", AccountService.Location.Type.stop.toString());
+                    jsonObject.put("time", Long.MAX_VALUE);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+
+                Log.w(TAG, "location send " + jsonObject + " to " + contactLocationShare.size());
+                StringMap msgs = new StringMap();
+                msgs.setRaw(CallService.MIME_GEOLOCATION, Blob.fromString(jsonObject.toString()));
+                Ringservice.sendAccountTextMessage(path.getAccountId(), path.getContactId(), msgs);
+            }
+
             mContactSharingSubject.onNext(contactLocationShare.keySet());
 
             if (contactLocationShare.isEmpty()) {
diff --git a/ring-android/libringclient/src/main/java/cx/ring/model/Account.java b/ring-android/libringclient/src/main/java/cx/ring/model/Account.java
index b1b872a79596168ae3ee3ea2f09e940a565c81af..acaf66d6c6614554a05b1dacadf8716681f0f339 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/model/Account.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/model/Account.java
@@ -1,8 +1,9 @@
 /*
- *  Copyright (C) 2004-2019 Savoir-faire Linux Inc.
+ *  Copyright (C) 2004-2020 Savoir-faire Linux Inc.
  *
  *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
  *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+ *  Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -900,26 +901,45 @@ public class Account {
         Log.w(TAG, "onLocationUpdate " + location.getPeer() + " " + location.getLatitude() + ",  " + location.getLongitude());
         CallContact contact = getContactFromCache(location.getPeer());
 
-        ContactLocation cl = new ContactLocation();
-        cl.timestamp = location.getDate();
-        cl.latitude = location.getLatitude();
-        cl.longitude = location.getLongitude();
-        cl.receivedDate = new Date();
+        switch (location.getType()) {
+            case position:
+                ContactLocation cl = new ContactLocation();
+                cl.timestamp = location.getDate();
+                cl.latitude = location.getLatitude();
+                cl.longitude = location.getLongitude();
+                cl.receivedDate = new Date();
+
+                Observable<ContactLocation> ls = contactLocations.get(contact);
+                if (ls == null) {
+                    ls = BehaviorSubject.createDefault(cl);
+                    contactLocations.put(contact, ls);
+                    mLocationSubject.onNext(contactLocations);
+                    ContactLocationEntry entry = new ContactLocationEntry();
+                    entry.contact = contact;
+                    entry.location = ls;
+                    mLocationStartedSubject.onNext(entry);
+                } else {
+                    if (ls.blockingFirst().timestamp < cl.timestamp)
+                        ((Subject<ContactLocation>) ls).onNext(cl);
+                }
+                break;
+
+            case stop:
+                forceExpireContact(contact);
+                break;
+        }
 
-        Observable<ContactLocation> ls = contactLocations.get(contact);
-        if (ls == null) {
-            ls = BehaviorSubject.createDefault(cl);
-            contactLocations.put(contact, ls);
+        return LOCATION_SHARING_EXPIRATION_MS;
+    }
+
+    synchronized private void forceExpireContact(CallContact contact) {
+        Log.w(TAG, "forceExpireContact " + contactLocations.size());
+        Observable<ContactLocation> cl = contactLocations.remove(contact);
+        if (cl != null) {
+            Log.w(TAG, "Contact stopped sharing location: " + contact.getDisplayName());
+            ((Subject<ContactLocation>) cl).onComplete();
             mLocationSubject.onNext(contactLocations);
-            ContactLocationEntry entry = new ContactLocationEntry();
-            entry.contact = contact;
-            entry.location = ls;
-            mLocationStartedSubject.onNext(entry);
-        } else {
-            if (ls.blockingFirst().timestamp < cl.timestamp)
-                ((Subject<ContactLocation>) ls).onNext(cl);
         }
-        return cl.receivedDate.getTime() + LOCATION_SHARING_EXPIRATION_MS;
     }
 
     synchronized public void maintainLocation() {
diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
index 012b335051b2b3a639f8a7bba7c3b6bc3e709340..624422f7d29b23e06e641c626bb86461f0bfa3eb 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
@@ -1,8 +1,9 @@
 /*
- *  Copyright (C) 2004-2019 Savoir-faire Linux Inc.
+ *  Copyright (C) 2004-2020 Savoir-faire Linux Inc.
  *
  *  Author: Thibault Wittemberg <thibault.wittemberg@savoirfairelinux.com>
  *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+ *  Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,6 +21,7 @@
  */
 package cx.ring.services;
 
+import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 
@@ -129,6 +131,11 @@ public class AccountService {
         Map<String, String> messages;
     }
     public static class Location {
+        public enum Type {
+            position,
+            stop
+        }
+        Type type;
         String accountId;
         String callId;
         Uri peer;
@@ -136,6 +143,10 @@ public class AccountService {
         double latitude;
         double longitude;
 
+        public Type getType() {
+            return type;
+        }
+
         public String getAccount() {
             return accountId;
         }
@@ -182,8 +193,15 @@ public class AccountService {
                     if (obj.size() < 2)
                         return Maybe.empty();
                     Location l = new Location();
-                    l.latitude = obj.get("lat").getAsDouble();
-                    l.longitude = obj.get("long").getAsDouble();
+
+                    JsonElement type = obj.get("type");
+                    if (type == null || type.getAsString().equals(Location.Type.position.toString())) {
+                        l.type = Location.Type.position;
+                        l.latitude = obj.get("lat").getAsDouble();
+                        l.longitude = obj.get("long").getAsDouble();
+                    } else if (type.getAsString().equals(Location.Type.stop.toString())) {
+                        l.type = Location.Type.stop;
+                    }
                     l.time = obj.get("time").getAsLong();
                     l.accountId = msg.accountId;
                     l.callId = msg.callId;