Phicomm R1 Smart Speaker Revived

4 minute read

Wireless Configuration

Most smart devices such as speakers, sockets, air conditioners are headless embedded devices, these devices need to be connected to the home network to make it a smart device, since they are lack of user interfaces such as keyboards or touchscreens, SmartConfig was created to make this process easier, and most of the domestic smart speaker vendors adopted this method.

Since the company behind R1 is not in operation any more, the app they developed does not work, we need to find a solution to configure its wireless connection, follow the steps to complete wifi configuration:

  1. Device power up.
  2. Press the round button on top of the speaker for 5s until the light at the bottom turned on, and prompting, starting network configuration.
  3. Connect your computer to access point named Phicomm_R1_xxxx, and check the IP address of the computer.
  4. Connect to it with adb and install the latest release of adb-join-wifi.apk
    adb connect 192.168.43.1
    adb push ~/Downloads/adb-join-wifi.apk /data/local/tmp/
    adb shell /system/bin/pm install -t /data/local/tmp/adb-join-wifi.apk
    adb shell am start -n com.steinwurf.adbjoinwifi/.MainActivity \
     -e ssid avocado -e password_type WPA -e password yourpassword
    

    You will see below screenshot if you have connection to it with scrcpy: adb join wifi

  5. Waiting for the voice direction, network configuration completed, actually this is not the succeeded completion, it is timeout, but it just works. This is because the wifi module works in either station mode or AP mode, when R1 is in network configuration mode, it works as an AP, it cannot connect to another router, until it switched back to station mode.

  6. Now you can find its IP address through router’s web interface, the device name is PHICOMM_R1_xxxx.

Device Binding

The speaker cannot work without binding, the device binding process involves interaction with server, which is dead now, you will see the follow messages in logcat:

07-11 18:30:15.528  1119  1333 D DeviceStateMgr: [ lineNumber =233 ] query device bound status
07-11 18:30:15.546  1119  1333 E HttpUtils: [ lineNumber =-1 ] http post error : Unable to resolve host "aios-home.hivoice.cn": No address associated with hostname
07-11 18:30:15.546  1119  1333 E DeviceStateMgr: [ lineNumber =239 ] queryDeviceBoundStatus error, query bound status error, response is null

From the above message we know the process id is 1119, the package name and the apk are easily to get with ps and pm path:

adb shell ps|grep 1119
u0_a8     1119  209   961540 127396 ffffffff 00000000 S com.phicomm.speaker.device
adb shell /system/bin/pm path com.phicomm.speaker.device
package:/system/app/Unisound/Unisound.apk

In order to make things clear we need to figure out what the app do when doing device binding.

Decompiling apk

REVERSE ENGINEERING APPS MAY BE ILLEGAL, THIS BLOG POST IS STRICTLY FOR EDUCATION PURPOSE.

jadx is a tool used for producing java source code from android dex or apk files.

First off, download the prebuilt release or build from source code:

git clone --depth 1 https://github.com/skylot/jadx.git
cd jadx
./gradlew dist
./build/jadx/bin/jadx-gui

Then decompile Unisound, we can locate the desired source code with the help of the log message: DeviceInfoUtils So, now we know we need to replay with a response with status set to 0 in json format to make isDeviceBounded to return true.

Add DNS Record to Pi-hole

To make the domain name aios-home.hivoice.cn resolvable, a record need to add to /etc/hosts in device or add to DNS server, I use Pi-hole as my local network DNS server: Pi-hole Local DNS Records

Make A Tiny HTTP Server

I am not going to make fully functional server, this piece of code builds a simple http server only handling post message:

#!/usr/bin/env python

import logging
import json
from http.server import HTTPServer, BaseHTTPRequestHandler

class MessageHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        user_status = {'status': '0'}
        content_len = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_len)
        logging.error("POST request,\nHeaders:\n%s\n\nBody:\n%s\n",
                str(self.headers), post_data.decode('utf-8'))

        self.send_response(200)
        self.send_header("Content-type", "application/json")
        self.end_headers()
        self.wfile.write(json.dumps(user_status).encode())

if __name__ == "__main__":
    serverip = ('', 19999)
    httpd = HTTPServer(serverip, MessageHandler)
    httpd.serve_forever()

Now, the speaker is working now, it is not as smart as before though, let’s play.

Streaming Music with Airplay

Playing music with a2dp connection is not a good choice as it is not stable when your cell phone and the speaker is not in the same room, and there are too many interferences at 2.4G Hz band, so airplay and DLNA are the best way to listen music with this good quality speaker.

  1. Make sure the speaker was connected to 5G wireless network.
  2. Activate bluetooth by saying, Open Bluetooth.
  3. Swipe up your phone to go to Control Center, touch airplay control at the top right corner and select the phicomm device under SPEAKERS &TVs:

Control Center airplay

The builtin airplay working well except you need to enable bluetooth every time you want to steam music with it.

Another way to do airplay is to install third-party apk, download hpplay from here, and install with adb connection:

adb push ~/Downloads/202005111602_hpplay-2003-release-v8.4.78_1.apk /data/local/tmp/hpplay.apk
adb shell /system/bin/pm install /data/local/tmp/hpplay.apk
adb shell am start com.hpplay.happyplay.aw/.WelcomeActivity

NOTE: When a new device trying to connect to the speaker, you need to select allow the connection when the app prompts you, this only need to set once.

Troubleshooting

Adb install failed with waiting for device

adb install ~/Downloads/202005111602_hpplay-2003-release-v8.4.78_1.apk
/Users/fdbai/Downloads/202005111602_hpplay-2003-release-v8.4.78_1.apk: 1 file pushed. 0.4 MB/s (19891275 bytes in 48.946s)
- waiting for device -
- waiting for device -
- waiting for device -

A: Use pm install instead.

Pm install failed with error: closed

adb shell pm install /data/local/tmp/hpplay.apk
error: closed

A: Message in logcat show that it is not supported to create sub process:

07-12 17:02:32.979   211   211 I create_subproc_thread: create_subproc not support <pm install /data/local/tmp/hpplay.apk>, so return -1

Use pm with full path(/system/bin/pm) works.

Choppy music when connected to 2.4G wireless network

Both builtin airplay and hpplay have this problem, with latter one, logcat show there are many resend packets:

07-10 17:25:26.764 19475 20119 D hpplay-base: [AudioStream:48] ###resend_callback,request seq:38005,count:10###
07-10 17:25:27.062 19475 20119 D hpplay-base: [AudioStream:48] ###resend_callback,request seq:38018,count:4###
07-10 17:25:27.154 19475 20119 D hpplay-base: [AudioStream:48] ###resend_callback,request seq:38023,count:2###
07-10 17:25:27.254 19475 20119 D hpplay-base: [AudioStream:48] ###resend_callback,request seq:38029,count:8###
07-10 17:25:27.644 19475 20119 D hpplay-base: [AudioStream:48] ###resend_callback,request seq:38051,count:11###

This issue disappears after switched to 5G wireless net work.