OK, so I figured it out. For posterity, here's the process I went through.
I took a complete backup using TWRP before I made anything any worse.
I was fortunate in that I had a pretty clear idea what I had done to make everything go wrong (restore "App+Data"). That meant I could do it again and try to get a sense of what the app had done. I used
find on the device to get a list of all the files that got changed when I did the bad restore. (busybox find doesn't have
-mmin so I did
touch somefile; [do the bad thing]; find . -newer somefile.) This gave me a list of "suspect" files: some stuff in the data partition
/data/data, some stuff in
/data/misc/profiles that I couldn't figure out; some stuff in
/data/app incl. an APK and ODEX stuff; and a handful of files in
packages.list, and a few others.
In Titanium Backup, the thing that was being restored ("Phone and Messaging") seems actually to be an alias for
com.android.providers.telephony -- when you click "Open system details", that is the "App" that comes up. This sorta matches the errors from the logs.
I found https://github.com/TilesOrganization/support/wiki/How-to-use-ADB-to-grant-permissions and https://gist.github.com/Arinerron/1bcaadc7b1cbeae77de0263f4e15156f which were interesting. When I tried to
adb pm dump the
com.android.providers.telephony package, I saw that it had
WRITE_APN_SETTINGS: granted=true. This increased my confidence that the permissions weren't really the issue.
I also looked through the
/data/data for the
com.android.providers.telephony package. Everything was owned by
system rather than by an app-specific account, but maybe that was OK.
restorecon didn't do anything on any of those files either.
Among the things that I tried in order to get stuff working again was to flash LineageOS 15.1 from a random post on XDA-Developers. That led to other problems but at least my messaging app didn't crash any more. This gave me a "known good" state. From this I
adb pulled a bunch of stuff from
I grepped through all the files looking for
telephony since I was pretty sure that was the thing that had been restored wrong. Nothing in
telephony in it (and I didn't really suspect permissions anyhow because of the
WRITE_APN_SETTINGS thing, above).
package-restrictions.xml seemed OK -- there was only one entry that referenced the
providers package and there was nothing in it except
telephony occurred in some other entries for other packages, but always under
enabled-components, so that seemed OK to me.)
telephony did show up in
packages.xml but I didn't understand enough of the data format to know what it was saying. (Attributes present include
By comparing the
packages.xml from the "broken" 14.1 install and the one from the "working" 15.1 install, I made some progress. From the 14.1 version:
<package name="com.android.providers.telephony" codePath="/data/app/com.android.providers.telephony-2" nativeLibraryPath="/data/app/com.android.providers.telephony-2/lib" publicFlags="1007402629" privateFlags="8" ft="16b952851c0" it="11e8f7d4c00" ut="16b95285980" version="25" sharedUserId="1001" installer="com.android.vending" isOrphaned="true">
<cert index="1" />
<!-- Some stuff that I disregarded because again I didn't think this was a permissions issue -->
<proper-signing-keyset identifier="1" />
<!-- much later... -->
<updated-package name="com.android.providers.telephony" codePath="/system/priv-app/TelephonyProvider" ft="11e8f7d4c00" it="11e8f7d4c00" ut="11e8f7d4c00" version="25" nativeLibraryPath="/system/priv-app/TelephonyProvider/lib" sharedUserId="1001" />
From the 15.1 "working" version:
<package name="com.android.providers.telephony" codePath="/system/priv-app/TelephonyProvider" nativeLibraryPath="/system/priv-app/TelephonyProvider/lib" publicFlags="1007402501" privateFlags="8" ft="11e8e4f2c40" it="11e8e4f2c40" ut="11e8e4f2c40" version="27" sharedUserId="1001" isOrphaned="true">
<cert index="1" />
<!-- snip -->
<proper-signing-keyset identifier="97" />
OK! It seems like the
nativeLibraryPath are screwed up. Possibly the
ut fields too. I still don't really know what those are for, but they correspond to fields in other apps in the
packages.xml file. Maybe they represent some kind of cross-application sharing. Anyhow, I used vim on the device to make some changes -- first removing
package-restrictions.xml, and (when that didn't work) editing
packages.xml to merge the two entries into one
<package> entry with the
ut fields from the
<updated-package> element (and then deleting
<updated-package>). I restarted the phone after each change to see if it worked. I can edit APNs/read SMS messages again so that's nice.
I was able to find https://dzone.com/articles/depth-android-package-manager which says that the
ut fields represent timestamps so probably they don't correspond to anything in particular. Probably the paths were the essential change.
Overall I would say that I think Android could one day become as approachable and user-friendly as Linux, given enough effort. I don't even think it would require anything difficult -- just more effort documenting how things work from the user/system administrator's perspective (to balance out all the extant documentation about how things work from the app developer's perspective). A good example would be "What is the package.xml file and what do ft, it, and ut stand for". Also it would be great if the source of truth for Android distributions wasn't an ad-encrusted forum like XDA, but hey, one step at a time.