Martin Vidner

Sep 18, 2017

After learning a couple of things I still only have a vague idea, but I am writing it down to help my future self, my team mates, and perhaps you too.

FCoE stands for "Fibre channel over Ethernet". Apparently if you have some disk on a Fibre Channel SAN (storage area network), you can use FCoE to extend the reachability of that disk to the ethernet parts of your network. It still needs to be a kind of special ethernet (10Gb, with special network cards) but that seems less special than FC hardware.

Shrink Your Code and Resources

Using minifyEnabled true in build.gradle shrunk the signed release build from 1,347,038 bytes to 786,674, which results in 2.39MB installed size. (Did not find a way to install this build from the IDE, used adb install -r ./app/app-release.apk.)

Changing proguardFiles from proguard-android.txt to proguard-android-optimize.txt slightly shrinks the APK to 771,406 bytes.

Adding shrinkResources true: 745,490 bytes, 2.21MB installed.

Code Bloat: Activity Base Class

It seems that now the main reason for bloat is the sheer amount of included code: 5 methods of mine vs 4823(!) methods from the android.* classes.

Changed the base class of the main activity from android.support.v7.app.AppCompatActivity to android.app.Activity but then adb install says "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]". adb uninstall net.vidner.justrollonedie solved it. But I wonder what would happen if my users on the app store wanted to update. Fortunately I have none :D

Code Bloat: API Version

I thought a 4x reduction in installed size was good enough, even if still bloated. I decided to fix one more thing before pushing an update to the store: the minimal required Android platform. (In the process of tinkering with a demo OpenGL app I discovered that android-8, supporting my old 2.2 Froyo phone, gets automatically downloaded if I declare it in the app manifest.)

So I did, and the side effect was perfect: all boilerplate code was gone and I ended up with a 17,282 byte APK, 44KB (kilobytes!) installed. Still too much for a microcontroller ;-) but good enough for Android.

Figuring out how to downgrade my code and layout and styles to still run on the older API seemed tricky at first, but then I simply generated a scratch project for android-9 and copied the differences. Then I changed one style name with the help of the API version filter (see screenshot).

Feb 28, 2017

Here I simply describe what it takes to publish an Android application that I described in the previous part, Building the First App.

Thanks to SUSE, my employer, for sponsoring a company-wide Hack Week which this project was a part of!

I will only deal with free apps: no cost for the user and no advertisements. I guess it would be easy to slap an advertisement module on it or put a minimal price tag on the app. But then it would be morally wrong for me to keep the profits without giving SUSE a cut, and the organizational and accounting process would quickly turn this into a lawyer's Hack Week. Scratch that.

Registering a Publisher Account: $25

I could have reused my existing Google account but decided to create a new one. The next step may put you off: a 25 USD registration fee is needed.

Then a fair amount of legalese, which I did skim through, and I was rewarded by the knowledge that Google apparently does not like developers to publish web browsers or search engines.

Publishing the App

When I thought my application was good enough to be published I went to the Developer Console to make a Store Listing.

Entered the app name, summary, long description; no surprise there, I had expected that from openSUSE RPM packaging. Then came the innovation: screenshots are required! In fact,

Two screenshots

a high-resolution icon (512x512 pixels)

a feature graphic (1024x500 px) which appears as the heading of the app listing page

Reportedly the new standard way to take a screenshot is Power + Volume Down. But that did not work for my Xperia phone. I had to enable the following setting, after which a Screenshot option appeared in the menu that appears after holding Power.

Settings, then

Device / Buttons, then

Power button / Power menu, there

enable Screenshot ☑.

For a moment I feared I would need to hire a designer for the icon, but then I told LibreOffice to write a 6 in a 360pt big font and used that. whew!

We do not process any user data so we check a box that we're Not submitting a privacy policy.

Now we are at a point in the form where it says that we need to submit a content rating, but it won't let us do it. I think it only allows to rate after the app has been uploaded.

Are we ready to upload the app code? Upload APK... bzzzt, wrong! must not upload a debug build. Did not find a way to make a production build in the GUI so used the CLI for a change: ./gradlew assemble... bzzzt, wrong! must not upload an unsigned build.

Signing software makes sense. Except the signing mechanism is unfamiliar to me, something involving a Java KeyStore. So I followed the manual: Sign Your App. Ended up with a file in my home directory and needing to enter two passwords each time I build a signed APK. At least no certification authority needed to be involved.

Content Rating: Category: Utility, No violence, No sexuality, No offensive language, No controlled substances (illegal drugs), No communication with other users, No sharing of personal information, No sharing of location, No digital goods purchasing, No Nazi symbolism, Not a browser or search engine.

Finally all information was there, I hit Publish, and I wondered how long the review process would take. It took about 3 hours on a European Tuesday noon.

Feb 27, 2017

Getting Started in Android Development: Part 1: Building the First App

Do you know programming and want to start with the Android platform? Just like me! Read on.

Thanks to SUSE, my employer, for sponsoring a company-wide Hack Week which this project was a part of!

In case you wonder why Android: it is a good balance of work and play. Android is not the coolest toy to play with at the moment, but it is the most versatile device that people are likely to have at hand, especially when traveling. And Android already outnumbers openSUSE and all other OSs in my household.

This is a three part series: 1) building an app, 2) publishing it on Google Play, 3) trimming it down. In this part, we'll set up the development environment, follow the official tutorial to build a trivial app, then build a trivial yet useful app of our own.

a screenshot of my first app

Installing the SDK

I am using openSUSE Leap 42.1 (x86_64). You will notice that I keep tallying the disk space taken. This is because I am a bit short of space on one of my machines, and need to have an idea how much cleanup is needed.

Got a slightly confusing notice about KVM emulator acceleration. It seems that if you have used KVM before on your machine, the SDK will use it out of the box. But even with acceleration, don't expect the emulator to be fast. If you have a real device, use that.

For the most part I simply followed the tutorial for building, installing, and running a trivial app that asks for a message and then displays it. The documentation feels excellent!

The one non-obvious part was choosing which Android version, in other words, which API level, to target. in the Target Android Devices dialog, the preselected option is API 15: Android 4.0.3 (IceCreamSandwich). That is presumably based on the current active device statistics which result in the app being compatible with 97% of devices. The oldest one is API 9: Android 2.3 (Gingerbread), which was a bit disappointing since my older phone from 2010 runs API 8, 2.2 (Froyo). (Don't worry, I eventually solved that in part 3.) Fortunately my newer phone has API 22: Android 5.1.1. Installed the API 22 platform too, to match the phone, about 100MB.

Connected my phone with a USB cable, pressed Run, and there it was! Don't worry, a buggy app will just crash and not affect the rest of your phone.

Just Roll One Die

Now it looked like I knew enough to make a useful app, so I did: Once my family was on a train with a board game table but we had no dice. So my first actual app is Just Roll One Die. A totally simple application that can just roll one ordinary six-faced die. Six faces ought to be enough for anybody. No pictures, just digits.

4. Extract the serial data (RFCOMM) from the Bluetooth dump

I learned the bare minimum needed about Bluetooth so it is very likely the
tool only works for this specific use case.

Originally I opened the btsnoop log with Wireshark and guessed my way
through the BT protocol layers. In the end the RFCOMM length field was harder
than usual to guess and half of my packets were wrong. So I resorted to
finding the appropriate part of the Linux kernel source to find out
the format.

5+6. Decode the EV3 protocol and dissassemble the EV3 instructions

The people of the ev3dev project have already
produced a disassembler which we will use in the next step. But that
one assumes you start with a program file (RBF).

Here we have a log containing not only the usual RBF instructions but also
System Commands.

A Device may have multiple Configurations, and only one can be active at
a time. Most devices have only one. Supporting multiple Configurations
is reportedly useful for offering more/less features when more/less
power is available. EV3 has only one configuration.

configuration = device.get_active_configuration()

A physical Device may have multiple Interfaces active at a time.
A typical example is a scanner-printer combo. An Interface may have multiple
Alternate Settings. They are kind of like Configurations, but easier to
switch.
I don't quite understand this, but they say that if you need Isochronous
Endpoints (read: audio or video), you must go to a non-primary
Alternate Setting. Anyway, EV3 has only one Interface with one Setting.

An Interface will typically have multiple Endpoints. The Endpoint 0 is
reserved for control functions by the USB standard so we need to use Endpoint
1 here.

The standard distinguishes between input and output endpoints, as well as four
transfer types, differing in latency and reliability. The nice thing is that
the Python library nicely allows to abstract all that away (unlike cough Ruby
cough) and we simply say to write to a non-control Endpoint.

Other than Robots?

Robots are great fun but unfortunately they do not come bundled with every
computer. Do you know of a device that we could use for demonstration
purposes? Everyone has a USB keyboard and mouse but I guess the OS will claim
them for input and not let you play.

The Full Script

Dec 12, 2016

I know Ruby but have little experience with web apps. If you're like me then this article could be useful.

I needed a way to browse API documentation of multiple related code repositories.
(Yes, it's YaST).

I made a tool for that in the form of a web application. This was really easy with
the Sinatra framework.

First I ran it locally on my machine for myself. Then I ran it on a machine in the company network
for team mates to use. It was a VM that I repurposed from a previous experiment. Then Pepa said
it would be nice to have it publicly accessible. How hard could that be?

I had heard that Heroku makes that sort of thing easy, and it turned to be true!

It's free.
A low profile app, that only needs to run occasionally, fits into their Free service plan.
It sleeps after 30 minutes and takes 10 seconds to wake up.

For IMG I used a SUSE-internal server with SLEnkins images.
The tricky part is knowing the right value for the --disk bus setting. At first I used the default but the machine wouldn't boot because it would see /dev/sda instead of /dev/vda it was expecting.

May 27, 2016

Call-graph makes a call graph among methods of a single Ruby file.
I made it to help me orient myself in unfamiliar legacy code and to help identify cohesive parts that could be split out.
Yes, it is quick and dirty.

Example

One file in YaST has around 2700 lines and 73 methods. The call graph below was made with

Nov 10, 2015

If this rings a bell but you can't quite remember why, here's an English version of the screen, and the spoiler for the puzzle is below it:

Spoiler: The line containing "passwd" is clipped at the (left) end, showing only "المحا" instead of "المحلي۔". This bug got popular in the YaST team because the localization testers dutifully reported every instance of a truncated label so the bug accumulated 22 duplicates. It only happened for the Arabic script which made it a bit more challenging to work with, but luckily I know the script and a few words.

Aug 2, 2013

As already announced on
Factory,
yast-devel,
and by
Lukáš:
YaST, the SUSE installation and configuration tool, has been automatically
translated from YCP, an in-house custom language, to Ruby. In the past 6 months, we have built a tool to translate 600.000 lines of code developed over the course of 12 years.

My role in the project was mainly shedding light on ancient details of the YCP
language and its interpreter. Stop pulling my beard, kids! Also, knowing Bison (the tool used to implement
the YCP parser in C++) I designed a part that transfers the comments. Mind
you, not only at the function or statement level, but from
inside of expressions
too. Fun!

May 16, 2011

After a problem with the organizers' equipment, kobliha's openSUSE laptop was used to watch the live stream from Skynet I/O Chrome keynote.
"Rule 1: Stay calm." Ralph Angenendt talks about problem solving.
Party!

Dec 22, 2010

Use case: I want to create an appliance image for a build farm worker machine. I don't know its hardware configuration beforehand; in particular, it may have multiple network interfaces and I don't want to bother figuring out which is which. I will simply include network-autoconfig.rpm and plug the cable into any socket before booting.

network-autoconfig helps setting up machines with multiple network interfaces. At the first boot, all available Ethernet interfaces are cycled until one is successfully configured with DHCP.

I have submitted it to openSUSE:Factory now. Enjoy it in the upcoming openSUSE 11.4!

Nov 9, 2010

I have made a new release of ruby-dbus, a Ruby language
binding for the D-Bus IPC system.
The main feature is a better binding of Ruby Exceptions to D-Bus Errors. See
below for an excerpt of the documentation.
Perhaps more importantly, the library is now primarily packaged
as a RubyGem (Issue#6).
Also I converted the tutorial from Webgen to Markdown.
Bug fixes:

Don't pass file descriptors to subprocesses,
they would not let go of the service name.

Aug 29, 2010

Root.cz recently ran an article (in Czech) about the n2n virtual private network sofware, an open alternative to Hamachi. I intend to use it to cross the NAT in my mom's DSL modem so that I can connect to her computer with ssh and VNC.
Thanks to happyman_eric and Grief, openSUSE Build Service already contained a package. I have made an improved version, adding an init script and a sysconfig file. Get the sources in my home project, or the binaries.

We value... respect for other persons and their contributions, for other opinions and beliefs. We listen to arguments and address problems in a constructive and open way. We believe that a diverse community based on mutual respect is the base for a creative and productive environment enabling the project to be truly successful. We don't tolerate social discrimination and aim at creating an environment where people feel accepted and safe from offense.

Aug 5, 2010

I have upgraded my office workstation to openSUSE 11.3 today. Here I document the migration so that you don't have to repeat my mistakes.

I went via the command line and ventured to keep all additional repos enabled. So switching the repos was done simply by sed -i "s/11\.2/11.3/g" /etc/zypp/repos.d/*

The KDE session crashed after kdelibs4-core had been updated. No big deal, so I ran zypper dup again.
The /home directory is mounted via NFS, so filesystem.rpm failed when it wanted to reset the permissions of /home. Updating it explicitly after unmounting /home was easy, only unmounting it was harder because the crashed session left processes still accessing the home. fuser -v /home found them.

The NFS mount is also authenticated by Kerberos and there is a bug so I got

Jul 22, 2010

Many on_signal could cause DBus.Error.LimitsExceeded (bnc#617350).
Don't add a match rule that already exists, enable removing match rules. Now only one handler for a rule is called (but it is possible for one signal to match more rules). This reverts the half-fix done to fix Issue#3.

Jul 2, 2010

I think one good way is to make sure that new people feel welcome when they join a conversation, be it on the forums, on IRC or on the mailing lists. Now this would be easier if we all had infinite time to read and answer all questions, but as we don't, I decided to focus somehow.

The forums provide a handy shortcut for the focus, labeling a user who made few posts as a "Puzzled Penguin". So I've made a simple service, a feed of http://forums.opensuse.org showing only the posts by newcomer users: http://vidner.net/martin/software/rss-creator-blacklist

(Actually right now it does not show Puzzled Penguins only but instead excludes the 100 most-posting users until I learn how to optimize the PHP code.)

"The openSUSE KIWI Image System provides a complete operating system image solution for Linux supported hardware platforms as well as for virtualisation systems like Xen Qemu or VMware."

"Puppet is an open source data center automation and configuration management framework. Puppet provides system administrators with a simplified platform that allows for consistent, transparent, and flexible systems management."

Mar 28, 2010

ruby-dbus has for a long time not worked on the default Ubuntu desktop. I thought I had fixed it in 0.2.12 but that was only for the server side. In fact, clients had another bug and I have released version 0.3.0 today to fix it.

Nov 9, 2009

Article update: it turns out many people come here hoping to find a solution and are disappointed to find only problems that I encountered.. Sorry, that's too bad. Until someone figures out a way to do it online, your best option is to boot off the Network installation CD (100MB).

On Saturday I upgraded my wife's laptop from openSUSE 11.0 to 11.2 RC. I did it using zypper dup, and there were some problems so here I describe them for the benefit of others who might try the same.

Edited /etc/zypp/repos.d/* to replace all 11.0 occurences with 11.2. It worked also for Packman and Videolan.

zypper in zypper offered a suspiciously large update. It turned out it wanted to switch from x86_64 to i586, boo! The fix was zypper in zypper.x86_64\>1

That did not go well. It installed the new rpm.rpm and then repo2solv failed, terminating the transaction. After that, I had the old libzypp and the new zypper, not working. So I manually downloaded the libraries and installed them using rpm, ignoring the broken dependencies for the yast2-* packages.

Changed commit.downloadMode to DownloadInHeaps in /etc/zypp/zypp.conf, which exists primarily to avoid the previous problem. But Murphy does know when to strike.

zypper dup

Note that from 11.1 to 11.2, I used the live upgrade method without such problems. But for 11.0, you may be better off booting from an installation disc.

Oct 15, 2009

Problem: After a reboot, /etc/resolv.conf says just # Generated by NetworkManager and the real data went to /etc/resolv.conf.netconfig. I have both eth0 and wlan0 activated by NM. My setup does not involve dial-up like Seife's.