diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
index 876f01de02..e1a4e3ac7b 100644
--- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
+++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt
@@ -111,6 +111,10 @@ class RxRoom(private val room: Room) {
         room.updateName(name, it)
     }
 
+    fun updateCanonicalAlias(alias: String): Completable = completableBuilder<Unit> {
+        room.updateCanonicalAlias(alias, it)
+    }
+
     fun updateHistoryReadability(readability: String) = completableBuilder<Unit> {
         room.updateHistoryReadability(readability, it)
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt
index 9bfaff00ca..f22e3d59f0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt
@@ -37,6 +37,11 @@ interface StateService {
      */
     fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
 
+    /**
+     * Update the canonical alias of the room
+     */
+    fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable
+
     /**
      * Update the history readability of the room
      */
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
index 77fcd9a9bb..7cc061d0ae 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt
@@ -111,6 +111,15 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
         )
     }
 
+    override fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable {
+        return sendStateEvent(
+                eventType = EventType.STATE_ROOM_CANONICAL_ALIAS,
+                body = mapOf("alias" to alias),
+                callback = callback,
+                stateKey = null
+        )
+    }
+
     override fun updateHistoryReadability(readability: String, callback: MatrixCallback<Unit>): Cancelable {
         return sendStateEvent(
                 eventType = EventType.STATE_ROOM_HISTORY_VISIBILITY,
diff --git a/vector/src/main/java/im/vector/riotx/features/form/FormEditTextWithButtonItem.kt b/vector/src/main/java/im/vector/riotx/features/form/FormEditTextWithButtonItem.kt
new file mode 100644
index 0000000000..0650c0f55c
--- /dev/null
+++ b/vector/src/main/java/im/vector/riotx/features/form/FormEditTextWithButtonItem.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.riotx.features.form
+
+import android.text.Editable
+import android.view.View
+import androidx.appcompat.widget.AppCompatButton
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import com.google.android.material.textfield.TextInputEditText
+import com.google.android.material.textfield.TextInputLayout
+import im.vector.riotx.R
+import im.vector.riotx.core.epoxy.VectorEpoxyHolder
+import im.vector.riotx.core.epoxy.VectorEpoxyModel
+import im.vector.riotx.core.platform.SimpleTextWatcher
+
+@EpoxyModelClass(layout = R.layout.item_form_text_input_with_button)
+abstract class FormEditTextWithButtonItem : VectorEpoxyModel<FormEditTextWithButtonItem.Holder>() {
+
+    @EpoxyAttribute
+    var hint: String? = null
+
+    @EpoxyAttribute
+    var value: String? = null
+
+    @EpoxyAttribute
+    var enabled: Boolean = true
+
+    @EpoxyAttribute
+    var buttonText: String? = null
+
+    @EpoxyAttribute
+    var onTextChange: ((String) -> Unit)? = null
+
+    @EpoxyAttribute
+    var onButtonClicked: ((View) -> Unit)? = null
+
+    private val onTextChangeListener = object : SimpleTextWatcher() {
+        override fun afterTextChanged(s: Editable) {
+            onTextChange?.invoke(s.toString())
+        }
+    }
+
+    override fun bind(holder: Holder) {
+        holder.textInputLayout.isEnabled = enabled
+        holder.textInputLayout.hint = hint
+
+        // Update only if text is different
+        if (holder.textInputEditText.text.toString() != value) {
+            holder.textInputEditText.setText(value)
+        }
+        holder.textInputEditText.isEnabled = enabled
+
+        holder.textInputEditText.addTextChangedListener(onTextChangeListener)
+
+        holder.textInputButton.text = buttonText
+
+        holder.textInputButton.setOnClickListener(onButtonClicked)
+    }
+
+    override fun shouldSaveViewState(): Boolean {
+        return false
+    }
+
+    override fun unbind(holder: Holder) {
+        super.unbind(holder)
+        holder.textInputEditText.removeTextChangedListener(onTextChangeListener)
+    }
+
+    class Holder : VectorEpoxyHolder() {
+        val textInputLayout by bind<TextInputLayout>(R.id.formTextInputTextInputLayout)
+        val textInputEditText by bind<TextInputEditText>(R.id.formTextInputTextInputEditText)
+        val textInputButton by bind<AppCompatButton>(R.id.formTextInputButton)
+    }
+}
diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt
index aadb6584a5..615a7bd7cd 100644
--- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt
+++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt
@@ -25,6 +25,7 @@ sealed class RoomSettingsAction : VectorViewModelAction {
     data class SetRoomTopic(val newTopic: String) : RoomSettingsAction()
     data class SetRoomAvatar(val image: MultiPickerImageType) : RoomSettingsAction()
     data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction()
+    data class SetRoomAlias(val alias: String) : RoomSettingsAction()
     object EnableEncryption : RoomSettingsAction()
     object Save : RoomSettingsAction()
 }
diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt
index f29c6cc65e..ca472b9de4 100644
--- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt
+++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt
@@ -44,6 +44,7 @@ class RoomSettingsController @Inject constructor(
         fun onTopicChanged(topic: String)
         fun onPhotoClicked()
         fun onHistoryVisibilityClicked()
+        fun onAliasChanged(alias: String)
     }
 
     private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color)
@@ -86,6 +87,17 @@ class RoomSettingsController @Inject constructor(
             }
         }
 
+        formEditTextItem {
+            id("alias")
+            /*enabled(enableFormElement)*/
+            value(data.newAlias ?: roomSummary.canonicalAlias)
+            hint(stringProvider.getString(R.string.room_settings_addresses_add_new_address))
+
+            onTextChange { text ->
+                callback?.onAliasChanged(text)
+            }
+        }
+
         buildProfileAction(
                 id = "historyReadability",
                 title = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_title),
diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt
index 8e25646637..7733f4323f 100644
--- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt
@@ -190,4 +190,8 @@ class RoomSettingsFragment @Inject constructor(
             RoomHistoryVisibility.WORLD_READABLE -> stringProvider.getString(R.string.notice_room_visibility_world_readable)
         }
     }
+
+    override fun onAliasChanged(alias: String) {
+        viewModel.handle(RoomSettingsAction.SetRoomAlias(alias))
+    }
 }
diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt
index 26da0bb478..d07c2befaf 100644
--- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt
@@ -89,6 +89,10 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
                 setState { copy(newHistoryVisibility = action.visibility) }
                 setState { copy(showSaveAction = shouldShowSaveAction(this)) }
             }
+            is RoomSettingsAction.SetRoomAlias -> {
+                setState { copy(newAlias = action.alias) }
+                setState { copy(showSaveAction = shouldShowSaveAction(this)) }
+            }
             is RoomSettingsAction.Save                     -> saveSettings()
         }
     }
@@ -97,6 +101,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
         val summary = state.roomSummary.invoke()
         return summary?.displayName != state.newName ||
                 summary?.topic != state.newTopic ||
+                summary?.canonicalAlias != state.newAlias ||
                 state.newHistoryVisibility != null ||
                 state.newAvatar != null
     }
@@ -115,6 +120,10 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
             operationList.add(room.rx().updateTopic(state.newTopic ?: ""))
         }
 
+        if (summary?.canonicalAlias != state.newAlias) {
+            operationList.add(room.rx().updateCanonicalAlias(state.newAlias ?: ""))
+        }
+
         if (state.newHistoryVisibility != null) {
             operationList.add(room.rx().updateHistoryReadability(state.newHistoryVisibility.name.toLowerCase(Locale.ROOT)))
         }
diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt
index e456f753c7..0502c7ebc5 100644
--- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt
+++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt
@@ -34,6 +34,7 @@ data class RoomSettingsViewState(
         val newTopic: String? = null,
         val newAvatar: MultiPickerImageType? = null,
         val newHistoryVisibility: RoomHistoryVisibility? = null,
+        val newAlias: String? = null,
         val showSaveAction: Boolean = false
 ) : MvRxState {
 
diff --git a/vector/src/main/res/layout/item_form_text_input_with_button.xml b/vector/src/main/res/layout/item_form_text_input_with_button.xml
new file mode 100644
index 0000000000..ccab8af3c1
--- /dev/null
+++ b/vector/src/main/res/layout/item_form_text_input_with_button.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?riotx_background"
+    android:minHeight="@dimen/item_form_min_height">
+
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/formTextInputTextInputLayout"
+        style="@style/VectorTextInputLayout"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="@dimen/layout_horizontal_margin"
+        android:layout_marginEnd="@dimen/layout_horizontal_margin"
+        app:layout_constraintBottom_toTopOf="@+id/formTextInputDivider"
+        app:layout_constraintEnd_toStartOf="@id/formTextInputButton"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <com.google.android.material.textfield.TextInputEditText
+            android:id="@+id/formTextInputTextInputEditText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            tools:hint="@string/create_room_name_hint" />
+
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <androidx.appcompat.widget.AppCompatButton
+        android:id="@+id/formTextInputButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/layout_horizontal_margin"
+        app:layout_constraintBottom_toBottomOf="@id/formTextInputTextInputLayout"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/formTextInputTextInputLayout"
+        android:background="?attr/colorAccent"
+        tools:text="Add"/>
+
+    <View
+        android:id="@+id/formTextInputDivider"
+        android:layout_width="0dp"
+        android:layout_height="1dp"
+        android:background="?riotx_header_panel_border_mobile"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>