MacOS bluetooth headset audio issue

Recently my bluetooth headset starts to act up when listening to music from MacOS. I initially thought it has died. Turns out it is an OS problem.

Basically if i use it as both input and output device, the sound quality is awful. So one solution is go to the sound setting and manually select input device internal microphone. Then looks like the audio will be back. However if you re-connect the device, it defaults to the bluetooth device as input again. quite annoying.

Another possible solution I found is to adjust the setting from the bluetooth explorer which can be downloaded from the Apple developer site‘s Hardware IO Tools for Xcode section. The downloaded the dmg is a bundle of various debugging tools. Open Bluetooth Explorer and go to Tools -> Audio Options -> force use aptX, and check the box. This will also improve the sound quality.

Advertisements

macos system launch config

MacOS Config options

MacOS boot service is mainly configured via three ways:
1.  the system preferences -> Users & Groups -> Login items
2. /System/Library/StartupItems and /Library/StartupItems/
3. launchd system initialization process configuration.

The first two are relatively simple, we will focus mainly on the third more complex launchd configuration optimization.
launchd is a key process for initializing the system environment under Mac OS. Similar to Linux under init, rc.

MacOS Boot Flow

Let’s take a look at the MacOS startup flow:
1, mac firmware activation, initialize hardware, load BootX boot.
2, BootX load kernel and kernel extension (kext).
3, the kernel starts the launchd process.
4, launchd Start the service daemon by following the plist configuration in the /System/Library/LaunchAgents,  System/Library/LaunchDaemons, ?/Library/LaunchDaemons, ?Library/LaunchAgents, ~/Library/LaunchAgents.

The five launch DIRs

After going thru the Mac OS startup flow, we can see that the plist files in the below five directories  ?/System/Library/LaunchAgents, ?/System/Library/LaunchDaemons, ?/Library/LaunchDaemons, ?Library/LaunchAgents?, ~/Library/LaunchAgents. are key to the system optimization.

some basic concepts

difference between/System/Library and /Library and ~/Library directory?

/System/Library directory is stored in Apple’s own software development.
The /Library directory is the third-party software that the system administrator holds.
~/Library/ is the user’s own third-party software.

What is the difference between LaunchDaemons and LaunchAgents?

LaunchDaemons is the service (daemon) that the user started before the login.
LaunchAgents is the service (daemon) that the user starts after landing.

SPEC

plist file format and the meaning of each field in the above mentioned five directories:

KEY DESCRIPTION REQUIRED
Label The name of the job yes
ProgramArguments Strings to pass to the program when it is executed yes
UserName The job will be run as the given user, who may not necessarily be the one who submitted it to launchd. no
inetdCompatibility Indicates that the daemon anticip to be run as if it were launched by? Inetd no
Program The path to your executable. This key can save the ProgramArguments key for flags and arguments. no
onDemand A? Boolean? Flag that defined if a job runs continuously or not no
RootDirectory The job will be? Chrooted? Into another directory no
ServiceIPC Any the daemon can speak IPC to launchd no
WatchPaths Allows launchd to start a job based on modifications at a file-system path no
QueueDirectories Similar to WatchPath, a queue will only watch an empty directory for new files no
StartInterval Used to schedule a job that runs on a repeating schedule. Specified as the number of seconds to wait between runs. no
StartCalendarInterval Job scheduling. The syntax is similar to cron. no
HardResourceLimits Controls restriction on the resources consumed by any job no
LowPriorityIO Tells the kernel that this task is of a low priority when doing file system I / O no
Sockets An array can be used to specify what socket the daemon will listen on for launch on demand no

Do not understand the above plist configuration? It is fine. Our optimization strategy is completely unload the service, so we do not care that much about plist in the configuration meaning.

Leverage launchctl

To start to optimize the disabled service, we need to use the Mac OS provides a tool instruction- launchctl
The launchctl directive sets a disable flag for the service. When launchd starts, it checks whether the service is disabled or not to determine whether the service needs to be enabled.

Method 1 to disable service

First find the disabled flag file /var/db/launchd.db/com.apple.launchd/overrides.plist to see if the service you want to disable has been disabled.
Some services have been disabled but are not listed in overrides.plist. At this point, you also need to check the service plist file Label field has been marked as Disable.

After confirming that the service is not disabled, we can disable the service by invoking the following command:
sudo launchctl unload plist-file-path

For example, I would like to disable spotlight :

sudo launchctl unload /System/Library/LaunchAgents/com.apple.Spotlight.plist

After disabling the service, restart Mac OS to take effect.

Method of banning service 2

a more effective and violent method (recommended)
Uninstall the service first
sudo launchctl unload /System/Library/LaunchAgents/com.apple.Spotlight.plist
And then the plist file mv to other directory backup. Reboot. Done.

I personally prefer this way to disable the service, so recommend it.

If you find that the service is disabled, the system or software is abnormal, you can restore the service by putting the file back to the original folder and run the following command:
sudo launchctl load plist-file-path

Note: Be very careful when disabling System-level service,. please get familiar what that system service does and do enough research before remove/disable it. Otherwise it may cause the system to fail to start. The safest thing to do is to stop it.

On the other hand for the user service, we can rest assured that we could disable, in case there are problems we just need to re-enable it.

Here is a list of my disabled services:
/Library/LaunchDaemons/com.google.keystone.daemon.plist? (Google Software Update)
/Library/LaunchAgents/com.google.keystone.root.agent? (Google Software Update)
~ / Library / LaunchAgents / com.google.keystone.agent.plist? (Google Software Update, users do not need to add the process of sudo)
~ / Library / LaunchAgents / com.apple.CSConfigDotMacCert-ken.wug \ @ me.com-SharedServices.Agent.plist (me.com’s shared services, I do not have)
/System/Library/LaunchDaemons/org.cups.cupsd.plist (printer)
/System/Library/LaunchDaemons/org.cups.cups-lpd.plist (printer)
/System/Library/LaunchDaemons/com.apple.blued.plist (bluetooth)
/System/Library/LaunchAgents/com.apple.AirPortBaseStationAgent.plist (apple wireless base station, i do not have this device)

I know the daemon (service) name, how to find the corresponding plist file?
Copy the process (service) name, and then to / System / Library / LaunchAgents,? / System / Library / LaunchDaemons,? / Library / LaunchDaemons,? Library / LaunchAgents, ~ / Library / LaunchAgents five directories, through the following command :

ll | grep process(service)-name such as
ll | grep blued
Found it in /System/Library/LaunchDaemons Next, follow the steps outlined above to disable the service

For McAfee

For React Native local development in iOS, i have to disable Mcafee daemon to free the 8081 port. For android, we can do the workaround by using 8088.

 cd /Library/LaunchDaemons
 sudo launchctl unload com.mcafee.agent.macmn.plist

disable the macos auto update notification

The auto update notification is pretty annoying since it popup everyday, and you need several clicks to make it disappear.

xmac-update-automatic

change from UI

I tried to disable it from System Preference -> App Store -> uncheck Automatically check for update. it does not that the checkbox keep checked after i reopen the system preference panel.

enable-or-disable-auto-apps-update-on-mac

Solution

Have to do it from command line via sudo.

	sudo ​softwareupdate --schedule off
	sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool FALSE

You can view the status by running
sudo defaults read /Library/Preferences/com.apple.SoftwareUpdate

clipboard in terminal(copy/paste)

Was watching a CD video with Semaphore and saw the guy in the video manipulating clipboard with pipe directly in the terminal. Pretty cool! Did some research on that.

OSX(MacOS)

In Mac, it is pretty straightforward with the built in pbcopy and pbpaste. (pasteboard copy / paste). Some examples:

cat my.key.pub | pbcopy

pbpaste > my.otherKey.pub

ps aux | grep myKeyWord | pbcopy

pbcopy < file.txt

pbpaste | grep myKeyWord

Linux

Take Ubuntu as example here. We can install a 16 kB program called xclip:

sudo apt-get install -y xclip

Then we can set alias so we can do the above operation like in osx. If you use bash then set your ~/.bashrc:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'

If you are like me using fish as main shell, then similarly add below to your ~/.config/fish/config.fish file.

alias pbcopy "xclip -selection clipboard"
alias pbpaste "xclip -selection clipboard -o"

OSX auto cleanup tmp ignore dir

Was putting some project related configs into the OS X /tmp directory, but found it was deleted. Turns out OS X has system scheduled cleanup job for the tmp dir. The config is under ‘/etc/defaults/periodic.conf‘.

I was first trying to leverage the provided ‘daily_clean_tmps_ignore’ parameter to exclude my directory but found not working, have to go to the source shell script to see why. The cleanup script locates in : ‘/etc/periodic/daily/110.clean-tmps’ which will go to the ‘/tmp’ dir and find command to get all the files that are 3 days old(atime, mtime, ctime) and not in the ignore list. So all the names we specified in the ‘daily_clean_tmps_ignore’ will be prefix the ‘! -name $pattern’ so that the $pattern could be excluded. However what i am trying to achieve here is for a directory and all its sub-files/dirs where using the -name is not enough.

We can use the -path option but we cannot add that thru configuration file.

Finally i decided to change the system script to achieve the ignoring by add a -name $pattern -prune option. After modification, it becomes:

 rc=$(for dir in $daily_clean_tmps_dirs
                do  
                    [ ."${dir#/}" != ."$dir" -a -d $dir ] && cd $dir && {
                        find -dx . -name 'MyDir' -prune -fstype local -type f $args -delete $print
                        find -dx . -name 'MyDir' -prune -fstype local ! -name . -type d $dargs -delete $print
                    } | sed "s,^\\.,  $dir,"
                done | tee /dev/stderr | wc -l)
            [ -z "$print" ] && rc=0
            [ $rc -gt 1 ] && rc=1
            set -f glob

A SO reference about -prune.

Install jdk 8 in Yosemite 10.10.2

While i was trying to downgrade JDK from 1.8.0._25 to 1.8.0_05 into the yosemite 10.10.2 so that i could use the DCEVM in my OSX.

 

I first remove the new version by just do a

sudo mv jdk1.8.0_25.jdk ~/Desktop/

Next step is to install the 1.8.0_05 which is the current latest version that DCEVM supports.However, I got the following error:

Your system has Mac OS X Version 10.10.2. This product can be installed on Version 10.7.3 or later.
Visit java.com/help for more information. 

Logically it looks really weird since apparently 10.10.2 is later than the 10.7.3. I think what they do is just compare the first digit so 1<7.

To install this, I have to spoof the OSX version.

1. go to  /System/Library/CoreServices and find the SystemVersion.plist which from its name we know contains the system version.

2. if you try to edit it directly you will find it r–r–r– readonly. To change it, you can either chmod it to 777 and modify content, or open it with some textEditor and do save as the same file name and extension. Then copy it back to the directory.

3. You can modify the version number to 9001 which is obviously larger than 10.10.1. I suggest you modify both ProductVersion and ProductUserVisibleVersion so that you could go to the “about this Mac” to verify the change.

4. Now you should be able to install without that error.

5. Do remember to change it back to whatever version you were before the modification.

 

.profile vs .bash_profile in OSX

According to the manual page that ships with OS X:

… it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

in summary: .profile works with sh or bash. However .bash_profile is bash-specific and will override .profile if present.

mac OS X environment checks .bash_profile, .bash_login, .profile in this order. It will run whichever is the highest in the hierarchy, so, if you have .bash_profile, it will not check .profile.