Explorar o código

Add Android Multi-SIM post

Thomas Dy %!s(int64=3) %!d(string=hai) anos
pai
achega
79538e9fd4

+ 43 - 0
content/posts/android-multisim.md

@@ -0,0 +1,43 @@
++++
+title = "Android Multisim Pre-5.1"
+date = 2021-09-12T19:37:22+09:00
+tags = [ "programming", "android" ]
++++
+
+**NOTE** if you're just looking for a library to use, there's [MultiSim](https://github.com/UseHover/MultiSim). I've never used this so I can't guarantee anything about it. It also only supports SIM information and not SMS.
+
+Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.
+
+Android's API only officially supported multiple SIM cards in 5.1 (API level 22) but Android phones with dual-SIM (and even triple-SIM) capabilities were already available at least as far back as 2.3 (API level 10) when I first needed to support it. Since there was no official API for this, the manufacturers just invented their own and of course each one implemented it in a different way.
+
+## Mediatek
+
+The first phone we started working on was a [Lenovo A60](https://www.gsmarena.com/lenovo_a60-4711.php) which used a Mediatek SOC. We somehow got a library from the manufacturer that let us use the dual-SIM functionality, but it was quite a pain to get working as there was limited documentation and we were quite new to Android development at the time.
+
+When we disassembled the library that they gave us, we noticed that the names they used for the additional functions were quite interesting. They were all the `TelephonyManager` and `SmsManager` methods with a `Gemini` suffix and they would take an additional `int` parameter in addition to the original.
+
+It turned out that these were available on the standard `TelephonyManager` instance and could be accessed via reflection. The `SmsManager` was a bit trickier but we ended up figuring out that there was a `android.telephony.gemini.GeminiSmsManager` class that had the functionality.
+
+In a different phone with a Mediatek SOC, this got renamed to `com.mediatek.telephony.gemini.SmsManager` for some reason and dropped the `Gemini` suffix only for the `SmsManager`.
+
+## Intel
+
+It was also around this time that Intel started making SOCs for smartphones. We had an [ASUS Fonepad 7](https://www.gsmarena.com/asus_fonepad_7_%282014%29-6394.php). Unlike with the Mediatek device, we didn't have a library to use here and had to use reflection to find the hidden classes / methods.
+
+What we found was that instead of having a single instance with every method taking a `sim` parameter, they instead had separate instances of `TelephonyManager` and `SmsManager` for each SIM. You would call `TelephonyManager.get2ndTm()` and `SmsManager.get2ndSmsManager()` to have access to the 2nd SIM.
+
+## Qualcomm
+
+The last phone I looked at was a [dual-SIM Moto G](https://www.gsmarena.com/motorola_moto_g_dual_sim-5978.php). What's interesting about this one is that the API completely changed in the upgrade from 4.4 to 5.0.
+
+On Android 4.4, the API was pretty close to the Mediatek one. You had a single instance that could dispatch to other SIMs by having an extra parameter on all the methods. These were in `android.telephony.MSimTelephonyManager` and `android.telephony.MSimSmsManager`.
+
+On Android 5.0, the API was a weird mix of all the above and also the introduction of `android.telephony.SubscriptionManager` which was quite close but not exactly the same as what ended up in the official API. Instead of `getActiveSubscriptionInfoList` there was `getActiveSubIdList` which only returned `long[]`.
+
+For the information that would normally exist in `SubscriptionInfo`, you had to query the main `TelephonyManager` instance which had methods with an extra `long` parameter for the subscription id. The `SmsManager` was simpler with just `getSmsManagerForSubscriber`.
+
+With Android 5.1, I assume they just switched to using the official API so this phone would have gone through 3 different multi-SIM APIs over the course of it's life.
+
+## Epilogue
+
+Around the release of Android 5.1, we stopped work on the app so I never actually got to use the official API myself ironically. We also never really got a big deployment so while I saw quite the variety of multi-SIM implementations, that's probably not all that's been out in the wild.

+ 33 - 22
output/index.html

@@ -36,6 +36,39 @@
 <main id="content" role="main">
 <div class="postindex">
 	
+	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
+		<header>
+			<h1 class="p-name entry-title" itemprop="headline">
+				<a href="/posts/android-multisim.html" class="u-url">Android Multisim Pre-5.1</a>
+			</h1>
+		</header>
+		<div class="e-content entry-content">
+			<p><strong>NOTE</strong> if you&rsquo;re just looking for a library to use, there&rsquo;s <a href="https://github.com/UseHover/MultiSim">MultiSim</a>. I&rsquo;ve never used this so I can&rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.</p>
+<p>Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.</p>
+<p>Android&rsquo;s API only officially supported multiple SIM cards in 5.1 (API level 22) but Android phones with dual-SIM (and even triple-SIM) capabilities were already available at least as far back as 2.3 (API level 10) when I first needed to support it. Since there was no official API for this, the manufacturers just invented their own and of course each one implemented it in a different way.</p>
+<h2 id="mediatek">Mediatek</h2>
+<p>The first phone we started working on was a <a href="https://www.gsmarena.com/lenovo_a60-4711.php">Lenovo A60</a> which used a Mediatek SOC. We somehow got a library from the manufacturer that let us use the dual-SIM functionality, but it was quite a pain to get working as there was limited documentation and we were quite new to Android development at the time.</p>
+<p>When we disassembled the library that they gave us, we noticed that the names they used for the additional functions were quite interesting. They were all the <code>TelephonyManager</code> and <code>SmsManager</code> methods with a <code>Gemini</code> suffix and they would take an additional <code>int</code> parameter in addition to the original.</p>
+<p>It turned out that these were available on the standard <code>TelephonyManager</code> instance and could be accessed via reflection. The <code>SmsManager</code> was a bit trickier but we ended up figuring out that there was a <code>android.telephony.gemini.GeminiSmsManager</code> class that had the functionality.</p>
+<p>In a different phone with a Mediatek SOC, this got renamed to <code>com.mediatek.telephony.gemini.SmsManager</code> for some reason and dropped the <code>Gemini</code> suffix only for the <code>SmsManager</code>.</p>
+<h2 id="intel">Intel</h2>
+<p>It was also around this time that Intel started making SOCs for smartphones. We had an <a href="https://www.gsmarena.com/asus_fonepad_7_%282014%29-6394.php">ASUS Fonepad 7</a>. Unlike with the Mediatek device, we didn&rsquo;t have a library to use here and had to use reflection to find the hidden classes / methods.</p>
+<p>What we found was that instead of having a single instance with every method taking a <code>sim</code> parameter, they instead had separate instances of <code>TelephonyManager</code> and <code>SmsManager</code> for each SIM. You would call <code>TelephonyManager.get2ndTm()</code> and <code>SmsManager.get2ndSmsManager()</code> to have access to the 2nd SIM.</p>
+<h2 id="qualcomm">Qualcomm</h2>
+<p>The last phone I looked at was a <a href="https://www.gsmarena.com/motorola_moto_g_dual_sim-5978.php">dual-SIM Moto G</a>. What&rsquo;s interesting about this one is that the API completely changed in the upgrade from 4.4 to 5.0.</p>
+<p>On Android 4.4, the API was pretty close to the Mediatek one. You had a single instance that could dispatch to other SIMs by having an extra parameter on all the methods. These were in <code>android.telephony.MSimTelephonyManager</code> and <code>android.telephony.MSimSmsManager</code>.</p>
+<p>On Android 5.0, the API was a weird mix of all the above and also the introduction of <code>android.telephony.SubscriptionManager</code> which was quite close but not exactly the same as what ended up in the official API. Instead of <code>getActiveSubscriptionInfoList</code> there was <code>getActiveSubIdList</code> which only returned <code>long[]</code>.</p>
+<p>For the information that would normally exist in <code>SubscriptionInfo</code>, you had to query the main <code>TelephonyManager</code> instance which had methods with an extra <code>long</code> parameter for the subscription id. The <code>SmsManager</code> was simpler with just <code>getSmsManagerForSubscriber</code>.</p>
+<p>With Android 5.1, I assume they just switched to using the official API so this phone would have gone through 3 different multi-SIM APIs over the course of it&rsquo;s life.</p>
+<h2 id="epilogue">Epilogue</h2>
+<p>Around the release of Android 5.1, we stopped work on the app so I never actually got to use the official API myself ironically. We also never really got a big deployment so while I saw quite the variety of multi-SIM implementations, that&rsquo;s probably not all that&rsquo;s been out in the wild.</p>
+
+		</div>
+		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2021-09-12">2021-09-12</time></small>
+		| <small class="commentline"><a href="/posts/android-multisim.html#isso-thread">Comments</a></small>
+	</article>
+	</article>
+	
 	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
 		<header>
 			<h1 class="p-name entry-title" itemprop="headline">
@@ -288,28 +321,6 @@ are good, I might not even need to finish it.</p>
 	</article>
 	</article>
 	
-	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
-		<header>
-			<h1 class="p-name entry-title" itemprop="headline">
-				<a href="/posts/haproxy-charset.html" class="u-url">Haproxy Charset</a>
-			</h1>
-		</header>
-		<div class="e-content entry-content">
-			<p>A common problem we encounter is for things like <em>ñ</em> not showing up correctly. This actually caused <a href="http://www.rappler.com/nation/politics/elections/2016/132894-human-error-hash-election-results-code-mismatch">some issues</a> in the recent Philippine elections, but this isn&rsquo;t about hash codes or anything like that.</p>
-<p>By default, we use UTF-8 for text storage and rendering. A problem is that browsers don&rsquo;t assume UTF-8 as the default and you need to have either a <code>&lt;meta charset=&quot;utf-8&quot; /&gt;</code> in the HTML or <code>Content-Type: text/html; charset=utf-8</code> in the headers. A few of our services don&rsquo;t set the <code>Content-Type</code> with the <code>charset=utf-8</code> part so you&rsquo;d get piñata instead of piñata.</p>
-<p>Being lazy, we usually just correct this at the reverse proxy side. It&rsquo;s trivial to do in nginx. You just need to add <code>charset utf-8;</code> to your configuration and you&rsquo;re good. For haproxy though, I couldn&rsquo;t readily find a solution for it and had to go through the docs to see what I could do.</p>
-<p>After a bit of experimenting, I had success with this:</p>
-<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text"># set content-type to utf-8 if not already
-acl has_charset hdr_sub(content-type) -i charset=
-rspirep (Content-Type.*) \1;\ charset=utf-8 unless has_charset
-</code></pre></div><p>This is probably not the best way to do it. Arguably, we should just fix our services to have the correct <code>Content-Type</code> in the first place, but I can do that some other time.</p>
-
-		</div>
-		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2016-06-24">2016-06-24</time></small>
-		| <small class="commentline"><a href="/posts/haproxy-charset.html#isso-thread">Comments</a></small>
-	</article>
-	</article>
-	
 </div>
 <nav class="postindexpager">
 	<ul class="pager clearfix">

+ 22 - 44
output/page/2.html

@@ -36,6 +36,28 @@
 <main id="content" role="main">
 <div class="postindex">
 	
+	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
+		<header>
+			<h1 class="p-name entry-title" itemprop="headline">
+				<a href="/posts/haproxy-charset.html" class="u-url">Haproxy Charset</a>
+			</h1>
+		</header>
+		<div class="e-content entry-content">
+			<p>A common problem we encounter is for things like <em>ñ</em> not showing up correctly. This actually caused <a href="http://www.rappler.com/nation/politics/elections/2016/132894-human-error-hash-election-results-code-mismatch">some issues</a> in the recent Philippine elections, but this isn&rsquo;t about hash codes or anything like that.</p>
+<p>By default, we use UTF-8 for text storage and rendering. A problem is that browsers don&rsquo;t assume UTF-8 as the default and you need to have either a <code>&lt;meta charset=&quot;utf-8&quot; /&gt;</code> in the HTML or <code>Content-Type: text/html; charset=utf-8</code> in the headers. A few of our services don&rsquo;t set the <code>Content-Type</code> with the <code>charset=utf-8</code> part so you&rsquo;d get piñata instead of piñata.</p>
+<p>Being lazy, we usually just correct this at the reverse proxy side. It&rsquo;s trivial to do in nginx. You just need to add <code>charset utf-8;</code> to your configuration and you&rsquo;re good. For haproxy though, I couldn&rsquo;t readily find a solution for it and had to go through the docs to see what I could do.</p>
+<p>After a bit of experimenting, I had success with this:</p>
+<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text"># set content-type to utf-8 if not already
+acl has_charset hdr_sub(content-type) -i charset=
+rspirep (Content-Type.*) \1;\ charset=utf-8 unless has_charset
+</code></pre></div><p>This is probably not the best way to do it. Arguably, we should just fix our services to have the correct <code>Content-Type</code> in the first place, but I can do that some other time.</p>
+
+		</div>
+		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2016-06-24">2016-06-24</time></small>
+		| <small class="commentline"><a href="/posts/haproxy-charset.html#isso-thread">Comments</a></small>
+	</article>
+	</article>
+	
 	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
 		<header>
 			<h1 class="p-name entry-title" itemprop="headline">
@@ -208,50 +230,6 @@ twanager bag default <span style="color:#0ff;font-weight:bold">&lt;&lt;EOF
 	</article>
 	</article>
 	
-	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
-		<header>
-			<h1 class="p-name entry-title" itemprop="headline">
-				<a href="/posts/console-keymap-switching.html" class="u-url">Console Keymap Switching</a>
-			</h1>
-		</header>
-		<div class="e-content entry-content">
-			<p>At the office, we have some people who use DVORAK. Normally, this isn&rsquo;t a problem. To each his own after all. It does become a bit problematic though, when we&rsquo;re dealing with the servers around the office.</p>
-<p>We normally leave the servers on QWERTY. After all, most people start off as QWERTY typists and migrate to something else. That said, it&rsquo;s apparently difficult to stay fluent in both. People tend to forget how to type in QWERTY once they learn DVORAK or something else. While it is true that they can just look a the keyboard while typing, my coworkers would prefer it to just be in DVORAK.</p>
-<p>For the console, they&rsquo;d typically do <code>sudo loadkeys dvorak</code> after logging in. The problem with this is, after they logout, the keymapping is still on DVORAK. This has been quite annoying for a few times since I can&rsquo;t even login to change the keymap. What I wanted was something like you get in the graphical login screens where you can pick your keymap before logging in. Apparently, there isn&rsquo;t a readily available thing for the console.</p>
-<p>I googled around for solutions and came across <a href="http://superuser.com/questions/548234/how-can-i-easily-toggle-between-dvorak-and-qwerty-keyboard-layouts-from-a-linux">a nice idea</a>. You could alias <code>asdf</code> to load the DVORAK mapping and <code>aoeu</code> (the equivalent to asdf in DVORAK) to load the QWERTY mapping. This actually makes sense since you don&rsquo;t really have to know where the letters are. The only problem is, you once again have to be logged in to change the key mappings.</p>
-<p>After some further searching, I found <a href="http://unix.stackexchange.com/questions/2884/toggle-between-dvorak-and-qwerty">something close to what I wanted</a>. Apparently, Alt+Up sends a KeyboardSignal keycode to the init process, which can act on that. It also works anywhere, even before being logged in. For SysVinit systems, you can just add a line to your inittab for a command to be run when Alt+Up is pressed.</p>
-<p>In the office, however, we generally use Arch Linux which uses SystemD. But apparently, it also has a mechanism of accepting the Alt+Up press. It runs the kbrequest target whenever it gets the keypress. <code>kbrequest.target</code> is normally aliased to run the rescue service though, so you have to manually create the file in <code>/etc/systemd/system/kbrequest.target</code> and fill it with a description:</p>
-<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#fff;font-weight:bold">[Unit]</span>
-<span style="color:#007f7f">Description</span>=<span style="color:#0ff;font-weight:bold">kbrequest target</span>
-</code></pre></div><p>We can then add a service to be run whenever the target is called. Something like <code>/etc/systemd/system/keymap-switch.service</code>:</p>
-<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#fff;font-weight:bold">[Unit]</span>
-<span style="color:#007f7f">Description</span>=<span style="color:#0ff;font-weight:bold">Keymap Switch Service</span>
-
-<span style="color:#fff;font-weight:bold">[Service]</span>
-<span style="color:#007f7f">Type</span>=<span style="color:#0ff;font-weight:bold">oneshot</span>
-<span style="color:#007f7f">ExecStart</span>=<span style="color:#0ff;font-weight:bold">/usr/local/bin/keymap-switch</span>
-
-<span style="color:#fff;font-weight:bold">[Install]</span>
-<span style="color:#007f7f">WantedBy</span>=<span style="color:#0ff;font-weight:bold">kbrequest.target</span>
-</code></pre></div><p>After enabling said service, we only need the actual keymap switcher, <code>/usr/local/bin/keymap-switch</code>. The StackOverflow answer provides different ways of detecting the current keymap so we know which one to switch to. Since we&rsquo;re using SystemD, we can use that instead for managing which keymap we&rsquo;re actually using. It stores the current settings inside <code>/etc/vconsole.conf</code>. We can also then switch keymaps by using <code>localectl set-keymap</code>.</p>
-<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#0f0;font-weight:bold">#!/bin/sh
-</span><span style="color:#0f0;font-weight:bold"></span><span style="color:#fff;font-weight:bold">source</span> /etc/vconsole.conf
-
-<span style="color:#fff;font-weight:bold">if</span> [ <span style="color:#0ff;font-weight:bold">&#34;</span>$TERM<span style="color:#0ff;font-weight:bold">&#34;</span> = <span style="color:#0ff;font-weight:bold">&#34;dumb&#34;</span> ]; <span style="color:#fff;font-weight:bold">then</span>
-  <span style="color:#fff;font-weight:bold">if</span> [ <span style="color:#0ff;font-weight:bold">&#34;</span>$KEYMAP<span style="color:#0ff;font-weight:bold">&#34;</span> = <span style="color:#0ff;font-weight:bold">&#34;dvorak&#34;</span> ]; <span style="color:#fff;font-weight:bold">then</span>
-    localectl set-keymap us
-  <span style="color:#fff;font-weight:bold">else</span>
-    localectl set-keymap dvorak
-  <span style="color:#fff;font-weight:bold">fi</span>
-<span style="color:#fff;font-weight:bold">fi</span>
-</code></pre></div><p>After putting it all together, it works! We can switch keymaps on the fly by simply pressing Alt+Up.</p>
-
-		</div>
-		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-10-29">2013-10-29</time></small>
-		| <small class="commentline"><a href="/posts/console-keymap-switching.html#isso-thread">Comments</a></small>
-	</article>
-	</article>
-	
 </div>
 <nav class="postindexpager">
 	<ul class="pager clearfix">

+ 44 - 20
output/page/3.html

@@ -36,6 +36,50 @@
 <main id="content" role="main">
 <div class="postindex">
 	
+	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
+		<header>
+			<h1 class="p-name entry-title" itemprop="headline">
+				<a href="/posts/console-keymap-switching.html" class="u-url">Console Keymap Switching</a>
+			</h1>
+		</header>
+		<div class="e-content entry-content">
+			<p>At the office, we have some people who use DVORAK. Normally, this isn&rsquo;t a problem. To each his own after all. It does become a bit problematic though, when we&rsquo;re dealing with the servers around the office.</p>
+<p>We normally leave the servers on QWERTY. After all, most people start off as QWERTY typists and migrate to something else. That said, it&rsquo;s apparently difficult to stay fluent in both. People tend to forget how to type in QWERTY once they learn DVORAK or something else. While it is true that they can just look a the keyboard while typing, my coworkers would prefer it to just be in DVORAK.</p>
+<p>For the console, they&rsquo;d typically do <code>sudo loadkeys dvorak</code> after logging in. The problem with this is, after they logout, the keymapping is still on DVORAK. This has been quite annoying for a few times since I can&rsquo;t even login to change the keymap. What I wanted was something like you get in the graphical login screens where you can pick your keymap before logging in. Apparently, there isn&rsquo;t a readily available thing for the console.</p>
+<p>I googled around for solutions and came across <a href="http://superuser.com/questions/548234/how-can-i-easily-toggle-between-dvorak-and-qwerty-keyboard-layouts-from-a-linux">a nice idea</a>. You could alias <code>asdf</code> to load the DVORAK mapping and <code>aoeu</code> (the equivalent to asdf in DVORAK) to load the QWERTY mapping. This actually makes sense since you don&rsquo;t really have to know where the letters are. The only problem is, you once again have to be logged in to change the key mappings.</p>
+<p>After some further searching, I found <a href="http://unix.stackexchange.com/questions/2884/toggle-between-dvorak-and-qwerty">something close to what I wanted</a>. Apparently, Alt+Up sends a KeyboardSignal keycode to the init process, which can act on that. It also works anywhere, even before being logged in. For SysVinit systems, you can just add a line to your inittab for a command to be run when Alt+Up is pressed.</p>
+<p>In the office, however, we generally use Arch Linux which uses SystemD. But apparently, it also has a mechanism of accepting the Alt+Up press. It runs the kbrequest target whenever it gets the keypress. <code>kbrequest.target</code> is normally aliased to run the rescue service though, so you have to manually create the file in <code>/etc/systemd/system/kbrequest.target</code> and fill it with a description:</p>
+<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#fff;font-weight:bold">[Unit]</span>
+<span style="color:#007f7f">Description</span>=<span style="color:#0ff;font-weight:bold">kbrequest target</span>
+</code></pre></div><p>We can then add a service to be run whenever the target is called. Something like <code>/etc/systemd/system/keymap-switch.service</code>:</p>
+<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#fff;font-weight:bold">[Unit]</span>
+<span style="color:#007f7f">Description</span>=<span style="color:#0ff;font-weight:bold">Keymap Switch Service</span>
+
+<span style="color:#fff;font-weight:bold">[Service]</span>
+<span style="color:#007f7f">Type</span>=<span style="color:#0ff;font-weight:bold">oneshot</span>
+<span style="color:#007f7f">ExecStart</span>=<span style="color:#0ff;font-weight:bold">/usr/local/bin/keymap-switch</span>
+
+<span style="color:#fff;font-weight:bold">[Install]</span>
+<span style="color:#007f7f">WantedBy</span>=<span style="color:#0ff;font-weight:bold">kbrequest.target</span>
+</code></pre></div><p>After enabling said service, we only need the actual keymap switcher, <code>/usr/local/bin/keymap-switch</code>. The StackOverflow answer provides different ways of detecting the current keymap so we know which one to switch to. Since we&rsquo;re using SystemD, we can use that instead for managing which keymap we&rsquo;re actually using. It stores the current settings inside <code>/etc/vconsole.conf</code>. We can also then switch keymaps by using <code>localectl set-keymap</code>.</p>
+<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#0f0;font-weight:bold">#!/bin/sh
+</span><span style="color:#0f0;font-weight:bold"></span><span style="color:#fff;font-weight:bold">source</span> /etc/vconsole.conf
+
+<span style="color:#fff;font-weight:bold">if</span> [ <span style="color:#0ff;font-weight:bold">&#34;</span>$TERM<span style="color:#0ff;font-weight:bold">&#34;</span> = <span style="color:#0ff;font-weight:bold">&#34;dumb&#34;</span> ]; <span style="color:#fff;font-weight:bold">then</span>
+  <span style="color:#fff;font-weight:bold">if</span> [ <span style="color:#0ff;font-weight:bold">&#34;</span>$KEYMAP<span style="color:#0ff;font-weight:bold">&#34;</span> = <span style="color:#0ff;font-weight:bold">&#34;dvorak&#34;</span> ]; <span style="color:#fff;font-weight:bold">then</span>
+    localectl set-keymap us
+  <span style="color:#fff;font-weight:bold">else</span>
+    localectl set-keymap dvorak
+  <span style="color:#fff;font-weight:bold">fi</span>
+<span style="color:#fff;font-weight:bold">fi</span>
+</code></pre></div><p>After putting it all together, it works! We can switch keymaps on the fly by simply pressing Alt+Up.</p>
+
+		</div>
+		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-10-29">2013-10-29</time></small>
+		| <small class="commentline"><a href="/posts/console-keymap-switching.html#isso-thread">Comments</a></small>
+	</article>
+	</article>
+	
 	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
 		<header>
 			<h1 class="p-name entry-title" itemprop="headline">
@@ -129,26 +173,6 @@ sed -i .bak <span style="color:#0ff;font-weight:bold">&#39;/^72/ s/,600/,60/&#39
 	</article>
 	</article>
 	
-	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
-		<header>
-			<h1 class="p-name entry-title" itemprop="headline">
-				<a href="/posts/graphserver.html" class="u-url">GraphServer</a>
-			</h1>
-		</header>
-		<div class="e-content entry-content">
-			<p>Link: <a href="http://graphserver.github.io/graphserver/">http://graphserver.github.io/graphserver/</a></p>
-<p>One other routing webapp I saw was GraphServer. It&rsquo;s actually more of a general purpose Graph library which supports GTFS and OSM data than an actual dedicated routing software like OpenTripPlanner. It&rsquo;s also based off python and C instead of Java, so it feels a lot less heavy.</p>
-<p>The instructions on the website are already pretty good. There are just some minor errors with it. Where it says <code>gs_gtfsdb_build</code>, you should actually use <code>gs_gtfsdb_compile</code>. Also, when running <code>gs_osmdb_compile</code> you might need to use <code>-t</code> for tolerant in case you follow the instructions on chopping up the original OSM data.</p>
-<p>A nice suggestion from the GraphServer instructions was to crop the OSM data to minimize the graph size. This is actually quite helpful if you downloaded the entire Philippine OSM dump. It reduced the original 900MB file to 135MB which was a lot more workable. I did hit a problem with their instructions though. The linked version of osmosis is an old one, which doesn&rsquo;t support 64-bit ids. The <a href="http://wiki.openstreetmap.org/wiki/Osmosis">latest version of Osmosis</a> easily did the job though.</p>
-<p>The actual routing though, was not exactly good. I only tried one route which should normally take 1-2 transfers, it suggested a route which involved 4+ transfers. It also didn&rsquo;t provide any alternate routes aside from that one. I&rsquo;m not sure if it&rsquo;s a limitation of the provided routeserver, but I didn&rsquo;t bother checking if it supported parameters which might provide better routes.</p>
-<p>I think graphserver could be useful, but it seems more involved than say OpenTripPlanner. There do seem to be people who use graphserver for their routing apps, but for the bounds of the contest, or just as a side project, it might require too much effort.</p>
-
-		</div>
-		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-07-23">2013-07-23</time></small>
-		| <small class="commentline"><a href="/posts/graphserver.html#isso-thread">Comments</a></small>
-	</article>
-	</article>
-	
 </div>
 <nav class="postindexpager">
 	<ul class="pager clearfix">

+ 20 - 34
output/page/4.html

@@ -36,6 +36,26 @@
 <main id="content" role="main">
 <div class="postindex">
 	
+	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
+		<header>
+			<h1 class="p-name entry-title" itemprop="headline">
+				<a href="/posts/graphserver.html" class="u-url">GraphServer</a>
+			</h1>
+		</header>
+		<div class="e-content entry-content">
+			<p>Link: <a href="http://graphserver.github.io/graphserver/">http://graphserver.github.io/graphserver/</a></p>
+<p>One other routing webapp I saw was GraphServer. It&rsquo;s actually more of a general purpose Graph library which supports GTFS and OSM data than an actual dedicated routing software like OpenTripPlanner. It&rsquo;s also based off python and C instead of Java, so it feels a lot less heavy.</p>
+<p>The instructions on the website are already pretty good. There are just some minor errors with it. Where it says <code>gs_gtfsdb_build</code>, you should actually use <code>gs_gtfsdb_compile</code>. Also, when running <code>gs_osmdb_compile</code> you might need to use <code>-t</code> for tolerant in case you follow the instructions on chopping up the original OSM data.</p>
+<p>A nice suggestion from the GraphServer instructions was to crop the OSM data to minimize the graph size. This is actually quite helpful if you downloaded the entire Philippine OSM dump. It reduced the original 900MB file to 135MB which was a lot more workable. I did hit a problem with their instructions though. The linked version of osmosis is an old one, which doesn&rsquo;t support 64-bit ids. The <a href="http://wiki.openstreetmap.org/wiki/Osmosis">latest version of Osmosis</a> easily did the job though.</p>
+<p>The actual routing though, was not exactly good. I only tried one route which should normally take 1-2 transfers, it suggested a route which involved 4+ transfers. It also didn&rsquo;t provide any alternate routes aside from that one. I&rsquo;m not sure if it&rsquo;s a limitation of the provided routeserver, but I didn&rsquo;t bother checking if it supported parameters which might provide better routes.</p>
+<p>I think graphserver could be useful, but it seems more involved than say OpenTripPlanner. There do seem to be people who use graphserver for their routing apps, but for the bounds of the contest, or just as a side project, it might require too much effort.</p>
+
+		</div>
+		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-07-23">2013-07-23</time></small>
+		| <small class="commentline"><a href="/posts/graphserver.html#isso-thread">Comments</a></small>
+	</article>
+	</article>
+	
 	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
 		<header>
 			<h1 class="p-name entry-title" itemprop="headline">
@@ -294,40 +314,6 @@ Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
 	</article>
 	</article>
 	
-	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
-		<header>
-			<h1 class="p-name entry-title" itemprop="headline">
-				<a href="/posts/open-trip-planner.html" class="u-url">Open Trip Planner</a>
-			</h1>
-		</header>
-		<div class="e-content entry-content">
-			<p>Link: <a href="http://www.opentripplanner.org">http://www.opentripplanner.org</a></p>
-<p><strong>TL;DR</strong> routes pretty well; data might cause weird issues</p>
-<p>OpenTripPlanner, as the name implies, is a routing app. Given point A and point B, it can provide possible routes by taking transit, riding a bike, or a mix of both. You can also specify options on how much walking you&rsquo;re willing to do or if you prefer fewer transfers over trip time. It could be a good competitor to the transit directions of Google Maps.</p>
-<p>It&rsquo;s actually in general use by the <a href="http://maps.trimet.org/">Trimet</a>, Portland&rsquo;s public transit system. I think a good reason why they deployed OpenTripPlanner is that Portland is a very bike friendly area. OpenTripPlanner&rsquo;s support for multi-modal (bike + transit) routing is one thing that even Google Maps doesn&rsquo;t have. This actually just screams <a href="http://philippine-transit.hackathome.com/prizes/">Inclusive Technology Award</a>.</p>
-<h3 id="setup">Setup</h3>
-<p>Getting OpenTripPlanner up and running involves a bit more downloading than OneBusAway. I&rsquo;d suggest going through the <a href="https://github.com/openplans/OpenTripPlanner/wiki/FiveMinutes">5-minute introduction</a> if you want to actually work with the Philippine data. You will also need to download the <a href="http://download.geofabrik.de/asia/philippines.html">Philippine data dump</a> from OSM. You will want the <code>osm.bz2</code> one (WARNING: 900MB unzipped).</p>
-<p>Once you get the webapp running, you&rsquo;ll notice the map tiles won&rsquo;t load correctly. This is because the default tileset used is from Mapbox which doesn&rsquo;t provide publicly free tilesets anymore. To actually see things on the map, you should click the + on the upper-right of the map and change the base layer to something like Open Street Map or OSM Mapquest. This has been fixed in their latest sources.</p>
-<h3 id="issues">Issues</h3>
-<p>The next thing you&rsquo;ll notice is that you can&rsquo;t search for a place. You can only just pick points on the map and route between those. I&rsquo;m still not exactly sure if it&rsquo;s supposed to have it, since the Trimet one has it. But even then adding it by using the Google Maps or MapQuest APIs shouldn&rsquo;t be too difficult.</p>
-<p>Another missing thing compared to the Trimet planner is being able to look at the routes akin to OneBusAway. And even then, Trimet&rsquo;s implementation isn&rsquo;t as good for exploring as OneBusAway is. Seeing the schedule or seeing which routes pass through a stop are left to an external site to do.</p>
-<p>There have been some weird issues with the routing though. A common occurence is the steps are somewhat disconnected (see image below). The left half shows OpenTripPlanner, it shows that you get off at a &ldquo;stop&rdquo; in EDSA and you should magically teleport to Arguilla street and start walking. To be fair, Google Maps (right half) shows that there is a street from the &ldquo;stop&rdquo; to Arguilla.</p>
-<p><img src="../galleries/transit/otp1.png" alt="OpenTripPlanner disconnected route"></p>
-<p>I can&rsquo;t say this isn&rsquo;t a bug. After all, OpenTripPlanner couldn&rsquo;t have magically known there really was a street there. If it did, it wouldn&rsquo;t just teleport you to the corner. I&rsquo;m more inclined to think though that this is a result of not having any shape data. As a result, OpenTripPlanner might try to assume the stop could mean places within a certain radius of where it was defined.</p>
-<p>Another weird issue that pops up sometimes is where it tells you to ride a jeep past the stop you want and then after a while, get off and ride a jeep back to your stop. A more general issue is that sometimes it won&rsquo;t give you the best route because it thinks you have to loop around to get to where you want to be. I don&rsquo;t really know how common this issue pops up though. It&rsquo;s highly dependent on where you put the marker. If you just move the marker down a little bit, it actually does give the correct route.</p>
-<p><img src="../galleries/transit/otp2.png" alt="OpenTripPlanner loopy route"></p>
-<p>Much like the earlier problem, I can&rsquo;t tell if this is a bug or it&rsquo;s a result of the bad data. Once again though, I think the issue is more of bad data. If you look at the plotted UP-Katipunan route, the stops aren&rsquo;t even on the road. This probably makes it more difficult for OpenTripPlanner to actually tell if the stop and road are connected.</p>
-<p><img src="../galleries/transit/upkatipunan.jpg" alt="UP Katipunan Route"></p>
-<p>From what they said during the launch, most of the route data was collected by getting a person to ride a jeep with a smartphone. That would explain why the coordinates aren&rsquo;t that exact. Even then, it would have been nice if they at least cleaned up the data by moving the stops to the road. They would have had to go over them to name the stops anyway.</p>
-<h3 id="conclusion">Conclusion</h3>
-<p>Overall though, I really like OpenTripPlanner. It handles most of the hard parts of the challenge. It provides a REST API for doing routing with the GTFS + OSM data. There&rsquo;s also a lot of potential for additional open source work. A lot can be done to improve the default webapp. Adding a default location searcher would greatly improve usability. Adding in the route viewing features of OneBusAway would also be nice. Alternatively, you could even write your own client that just interfaces with the API.</p>
-
-		</div>
-		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-07-09">2013-07-09</time></small>
-		| <small class="commentline"><a href="/posts/open-trip-planner.html#isso-thread">Comments</a></small>
-	</article>
-	</article>
-	
 </div>
 <nav class="postindexpager">
 	<ul class="pager clearfix">

+ 34 - 0
output/page/5.html

@@ -36,6 +36,40 @@
 <main id="content" role="main">
 <div class="postindex">
 	
+	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
+		<header>
+			<h1 class="p-name entry-title" itemprop="headline">
+				<a href="/posts/open-trip-planner.html" class="u-url">Open Trip Planner</a>
+			</h1>
+		</header>
+		<div class="e-content entry-content">
+			<p>Link: <a href="http://www.opentripplanner.org">http://www.opentripplanner.org</a></p>
+<p><strong>TL;DR</strong> routes pretty well; data might cause weird issues</p>
+<p>OpenTripPlanner, as the name implies, is a routing app. Given point A and point B, it can provide possible routes by taking transit, riding a bike, or a mix of both. You can also specify options on how much walking you&rsquo;re willing to do or if you prefer fewer transfers over trip time. It could be a good competitor to the transit directions of Google Maps.</p>
+<p>It&rsquo;s actually in general use by the <a href="http://maps.trimet.org/">Trimet</a>, Portland&rsquo;s public transit system. I think a good reason why they deployed OpenTripPlanner is that Portland is a very bike friendly area. OpenTripPlanner&rsquo;s support for multi-modal (bike + transit) routing is one thing that even Google Maps doesn&rsquo;t have. This actually just screams <a href="http://philippine-transit.hackathome.com/prizes/">Inclusive Technology Award</a>.</p>
+<h3 id="setup">Setup</h3>
+<p>Getting OpenTripPlanner up and running involves a bit more downloading than OneBusAway. I&rsquo;d suggest going through the <a href="https://github.com/openplans/OpenTripPlanner/wiki/FiveMinutes">5-minute introduction</a> if you want to actually work with the Philippine data. You will also need to download the <a href="http://download.geofabrik.de/asia/philippines.html">Philippine data dump</a> from OSM. You will want the <code>osm.bz2</code> one (WARNING: 900MB unzipped).</p>
+<p>Once you get the webapp running, you&rsquo;ll notice the map tiles won&rsquo;t load correctly. This is because the default tileset used is from Mapbox which doesn&rsquo;t provide publicly free tilesets anymore. To actually see things on the map, you should click the + on the upper-right of the map and change the base layer to something like Open Street Map or OSM Mapquest. This has been fixed in their latest sources.</p>
+<h3 id="issues">Issues</h3>
+<p>The next thing you&rsquo;ll notice is that you can&rsquo;t search for a place. You can only just pick points on the map and route between those. I&rsquo;m still not exactly sure if it&rsquo;s supposed to have it, since the Trimet one has it. But even then adding it by using the Google Maps or MapQuest APIs shouldn&rsquo;t be too difficult.</p>
+<p>Another missing thing compared to the Trimet planner is being able to look at the routes akin to OneBusAway. And even then, Trimet&rsquo;s implementation isn&rsquo;t as good for exploring as OneBusAway is. Seeing the schedule or seeing which routes pass through a stop are left to an external site to do.</p>
+<p>There have been some weird issues with the routing though. A common occurence is the steps are somewhat disconnected (see image below). The left half shows OpenTripPlanner, it shows that you get off at a &ldquo;stop&rdquo; in EDSA and you should magically teleport to Arguilla street and start walking. To be fair, Google Maps (right half) shows that there is a street from the &ldquo;stop&rdquo; to Arguilla.</p>
+<p><img src="../galleries/transit/otp1.png" alt="OpenTripPlanner disconnected route"></p>
+<p>I can&rsquo;t say this isn&rsquo;t a bug. After all, OpenTripPlanner couldn&rsquo;t have magically known there really was a street there. If it did, it wouldn&rsquo;t just teleport you to the corner. I&rsquo;m more inclined to think though that this is a result of not having any shape data. As a result, OpenTripPlanner might try to assume the stop could mean places within a certain radius of where it was defined.</p>
+<p>Another weird issue that pops up sometimes is where it tells you to ride a jeep past the stop you want and then after a while, get off and ride a jeep back to your stop. A more general issue is that sometimes it won&rsquo;t give you the best route because it thinks you have to loop around to get to where you want to be. I don&rsquo;t really know how common this issue pops up though. It&rsquo;s highly dependent on where you put the marker. If you just move the marker down a little bit, it actually does give the correct route.</p>
+<p><img src="../galleries/transit/otp2.png" alt="OpenTripPlanner loopy route"></p>
+<p>Much like the earlier problem, I can&rsquo;t tell if this is a bug or it&rsquo;s a result of the bad data. Once again though, I think the issue is more of bad data. If you look at the plotted UP-Katipunan route, the stops aren&rsquo;t even on the road. This probably makes it more difficult for OpenTripPlanner to actually tell if the stop and road are connected.</p>
+<p><img src="../galleries/transit/upkatipunan.jpg" alt="UP Katipunan Route"></p>
+<p>From what they said during the launch, most of the route data was collected by getting a person to ride a jeep with a smartphone. That would explain why the coordinates aren&rsquo;t that exact. Even then, it would have been nice if they at least cleaned up the data by moving the stops to the road. They would have had to go over them to name the stops anyway.</p>
+<h3 id="conclusion">Conclusion</h3>
+<p>Overall though, I really like OpenTripPlanner. It handles most of the hard parts of the challenge. It provides a REST API for doing routing with the GTFS + OSM data. There&rsquo;s also a lot of potential for additional open source work. A lot can be done to improve the default webapp. Adding a default location searcher would greatly improve usability. Adding in the route viewing features of OneBusAway would also be nice. Alternatively, you could even write your own client that just interfaces with the API.</p>
+
+		</div>
+		<small class="dateline">Posted: <time class="published dt-published" itemprop="datePublished" datetime="2013-07-09">2013-07-09</time></small>
+		| <small class="commentline"><a href="/posts/open-trip-planner.html#isso-thread">Comments</a></small>
+	</article>
+	</article>
+	
 	<article class="h-entry post-text" itemscope itemtype="http://schema.org/Blog">
 		<header>
 			<h1 class="p-name entry-title" itemprop="headline">

+ 5 - 0
output/posts.html

@@ -40,6 +40,11 @@
 	</header>
 	<ul class="postlist">
 		
+		<li>
+			<a class="listtitle" href="/posts/android-multisim.html">Android Multisim Pre-5.1</a>
+			<span class="entry-meta"><time itemprop="datePublished" datetime="2021-09-12">2021-09-12</time></span>
+		</li>
+		
 		<li>
 			<a class="listtitle" href="/posts/isp-issues.html">ISP Issues</a>
 			<span class="entry-meta"><time itemprop="datePublished" datetime="2018-08-16">2018-08-16</time></span>

+ 132 - 0
output/posts/android-multisim.html

@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+	<meta charset="utf-8">
+	<meta name="generator" content="Hugo 0.88.0" />
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<link rel="stylesheet" href="/assets/css/theme.css">
+	<link rel="alternate" href="/rss.xml" type="application/rss+xml" title="Pleasant Programmer">
+	<script type="text/javascript" src="//use.typekit.net/iwm5axp.js"></script>
+	<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
+	<title>Android Multisim Pre-5.1 - Pleasant Programmer</title>
+</head>
+
+<body>
+	<header id="header" role="banner">
+		<div id="thomas">
+			<img src="/assets/img/thomas.gif" alt="DJ THOMAS IN DA HAUS">
+			<img src="/assets/img/thomas.png" alt="Pleasant Programmer">
+		</div>
+		<h1 class="site-title"><a href="/">Pleasant Programmer</a></h1>
+		<nav id="menu" role="navigation">
+			<ul>
+				<li class="twitter">
+					<a href="http://twitter.com/pleasantprog">@pleasantprog</a>
+				</li>
+				<li><a href="/pages/projects.html">projects</a></li>
+				<li><a href="/posts.html">archives</a></li>
+				<li><a href="/tags.html">tags</a></li>
+				<li><a href="/rss.xml">rss</a></li>
+			</ul>
+		</nav>
+	</header>
+	<div id="container">
+
+
+<main id="content" role="main">
+<article itemscope itemtype="http://schema.org/BlogPosting">
+	<h1 class="p-name entry-title" itemprop="headline name">
+		<a href="/posts/android-multisim.html">Android Multisim Pre-5.1</a></h1>
+	<small>
+		<span class="dateline">Posted: <time itemprop="datePublished" datetime="2021-09-12">2021-09-12</time></span>
+		| More posts about
+		
+		<a class="tag p-category" href="/tags/programming.html" rel="tag">
+			programming
+		</a>
+		
+		<a class="tag p-category" href="/tags/android.html" rel="tag">
+			android
+		</a>
+		
+	</small>
+	<div class="e-content entry-content" itemprop="entry-text">
+		<p><strong>NOTE</strong> if you&rsquo;re just looking for a library to use, there&rsquo;s <a href="https://github.com/UseHover/MultiSim">MultiSim</a>. I&rsquo;ve never used this so I can&rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.</p>
+<p>Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.</p>
+<p>Android&rsquo;s API only officially supported multiple SIM cards in 5.1 (API level 22) but Android phones with dual-SIM (and even triple-SIM) capabilities were already available at least as far back as 2.3 (API level 10) when I first needed to support it. Since there was no official API for this, the manufacturers just invented their own and of course each one implemented it in a different way.</p>
+<h2 id="mediatek">Mediatek</h2>
+<p>The first phone we started working on was a <a href="https://www.gsmarena.com/lenovo_a60-4711.php">Lenovo A60</a> which used a Mediatek SOC. We somehow got a library from the manufacturer that let us use the dual-SIM functionality, but it was quite a pain to get working as there was limited documentation and we were quite new to Android development at the time.</p>
+<p>When we disassembled the library that they gave us, we noticed that the names they used for the additional functions were quite interesting. They were all the <code>TelephonyManager</code> and <code>SmsManager</code> methods with a <code>Gemini</code> suffix and they would take an additional <code>int</code> parameter in addition to the original.</p>
+<p>It turned out that these were available on the standard <code>TelephonyManager</code> instance and could be accessed via reflection. The <code>SmsManager</code> was a bit trickier but we ended up figuring out that there was a <code>android.telephony.gemini.GeminiSmsManager</code> class that had the functionality.</p>
+<p>In a different phone with a Mediatek SOC, this got renamed to <code>com.mediatek.telephony.gemini.SmsManager</code> for some reason and dropped the <code>Gemini</code> suffix only for the <code>SmsManager</code>.</p>
+<h2 id="intel">Intel</h2>
+<p>It was also around this time that Intel started making SOCs for smartphones. We had an <a href="https://www.gsmarena.com/asus_fonepad_7_%282014%29-6394.php">ASUS Fonepad 7</a>. Unlike with the Mediatek device, we didn&rsquo;t have a library to use here and had to use reflection to find the hidden classes / methods.</p>
+<p>What we found was that instead of having a single instance with every method taking a <code>sim</code> parameter, they instead had separate instances of <code>TelephonyManager</code> and <code>SmsManager</code> for each SIM. You would call <code>TelephonyManager.get2ndTm()</code> and <code>SmsManager.get2ndSmsManager()</code> to have access to the 2nd SIM.</p>
+<h2 id="qualcomm">Qualcomm</h2>
+<p>The last phone I looked at was a <a href="https://www.gsmarena.com/motorola_moto_g_dual_sim-5978.php">dual-SIM Moto G</a>. What&rsquo;s interesting about this one is that the API completely changed in the upgrade from 4.4 to 5.0.</p>
+<p>On Android 4.4, the API was pretty close to the Mediatek one. You had a single instance that could dispatch to other SIMs by having an extra parameter on all the methods. These were in <code>android.telephony.MSimTelephonyManager</code> and <code>android.telephony.MSimSmsManager</code>.</p>
+<p>On Android 5.0, the API was a weird mix of all the above and also the introduction of <code>android.telephony.SubscriptionManager</code> which was quite close but not exactly the same as what ended up in the official API. Instead of <code>getActiveSubscriptionInfoList</code> there was <code>getActiveSubIdList</code> which only returned <code>long[]</code>.</p>
+<p>For the information that would normally exist in <code>SubscriptionInfo</code>, you had to query the main <code>TelephonyManager</code> instance which had methods with an extra <code>long</code> parameter for the subscription id. The <code>SmsManager</code> was simpler with just <code>getSmsManagerForSubscriber</code>.</p>
+<p>With Android 5.1, I assume they just switched to using the official API so this phone would have gone through 3 different multi-SIM APIs over the course of it&rsquo;s life.</p>
+<h2 id="epilogue">Epilogue</h2>
+<p>Around the release of Android 5.1, we stopped work on the app so I never actually got to use the official API myself ironically. We also never really got a big deployment so while I saw quite the variety of multi-SIM implementations, that&rsquo;s probably not all that&rsquo;s been out in the wild.</p>
+
+	</div>
+	<aside class="postpromonav">
+		<nav>
+			<ul class="pager clearfix">
+				
+				<li class="previous">
+					<a href="/posts/isp-issues.html" rel="prev" title="ISP Issues">&larr; Previous post</a>
+				</li>
+				
+				
+			</ul>
+		</nav>
+	</aside>
+	<section class="comments">
+		<script
+	data-isso="https://isso.pleasantprogrammer.com/"
+	data-isso-require-author="true"
+	data-isso-vote="false"
+	src="https://isso.pleasantprogrammer.com/js/embed.min.js">
+</script>
+<section id="isso-thread"></section>
+
+	</section>
+</article>
+</main>
+
+
+	<footer id="footer" role="contentinfo">
+		<p>
+		<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_US">
+			<img alt="CC-BY-SA" style="border-width:0" src="https://licensebuttons.net/l/by-sa/3.0/80x15.png">
+		</a> &copy; 2020 Thomas Dy - Powered by <a href="http://gohugo.io">Hugo</a></p>
+	</footer>
+</div>
+
+<script src="/assets/js/konami.js"></script>
+<script>
+var easter_egg = new Konami();
+easter_egg.code = function() {
+	var el = document.getElementById('thomas');
+	if(el.className == "whoa") {
+		el.className = "";
+	}
+	else {
+		el.className = "whoa";
+	}
+	document.body.scrollTop = document.documentElement.scrollTop = 0;
+}
+easter_egg.load();
+
+
+
+</script>
+
+
+
+</body>
+</html>
+

+ 4 - 0
output/posts/isp-issues.html

@@ -63,6 +63,10 @@
 				</li>
 				
 				
+				<li class="next">
+					<a href="/posts/android-multisim.html" rel="next" title="Android Multisim Pre-5.1">Next post &rarr;</a>
+				</li>
+				
 			</ul>
 		</nav>
 	</aside>

+ 31 - 1
output/posts/rss.xml

@@ -6,11 +6,41 @@
     <description>Recent content in Posts on Pleasant Programmer</description>
     <generator>Hugo -- gohugo.io</generator>
     <language>en-us</language>
-    <lastBuildDate>Thu, 16 Aug 2018 23:03:05 +0900</lastBuildDate>
+    <lastBuildDate>Sun, 12 Sep 2021 19:37:22 +0900</lastBuildDate>
     
 	<atom:link href="https://pleasantprogrammer.com/posts/rss.xml" rel="self" type="application/rss+xml" />
     
     
+    <item>
+      <title>Android Multisim Pre-5.1</title>
+      <link>https://pleasantprogrammer.com/posts/android-multisim.html</link>
+      <pubDate>Sun, 12 Sep 2021 19:37:22 +0900</pubDate>
+      
+      <guid>https://pleasantprogrammer.com/posts/android-multisim.html</guid>
+      <description>NOTE if you&amp;rsquo;re just looking for a library to use, there&amp;rsquo;s MultiSim. I&amp;rsquo;ve never used this so I can&amp;rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.
+Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.</description>
+      <content:encoded>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; if you&amp;rsquo;re just looking for a library to use, there&amp;rsquo;s &lt;a href=&#34;https://github.com/UseHover/MultiSim&#34;&gt;MultiSim&lt;/a&gt;. I&amp;rsquo;ve never used this so I can&amp;rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.&lt;/p&gt;
+&lt;p&gt;Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.&lt;/p&gt;
+&lt;p&gt;Android&amp;rsquo;s API only officially supported multiple SIM cards in 5.1 (API level 22) but Android phones with dual-SIM (and even triple-SIM) capabilities were already available at least as far back as 2.3 (API level 10) when I first needed to support it. Since there was no official API for this, the manufacturers just invented their own and of course each one implemented it in a different way.&lt;/p&gt;
+&lt;h2 id=&#34;mediatek&#34;&gt;Mediatek&lt;/h2&gt;
+&lt;p&gt;The first phone we started working on was a &lt;a href=&#34;https://www.gsmarena.com/lenovo_a60-4711.php&#34;&gt;Lenovo A60&lt;/a&gt; which used a Mediatek SOC. We somehow got a library from the manufacturer that let us use the dual-SIM functionality, but it was quite a pain to get working as there was limited documentation and we were quite new to Android development at the time.&lt;/p&gt;
+&lt;p&gt;When we disassembled the library that they gave us, we noticed that the names they used for the additional functions were quite interesting. They were all the &lt;code&gt;TelephonyManager&lt;/code&gt; and &lt;code&gt;SmsManager&lt;/code&gt; methods with a &lt;code&gt;Gemini&lt;/code&gt; suffix and they would take an additional &lt;code&gt;int&lt;/code&gt; parameter in addition to the original.&lt;/p&gt;
+&lt;p&gt;It turned out that these were available on the standard &lt;code&gt;TelephonyManager&lt;/code&gt; instance and could be accessed via reflection. The &lt;code&gt;SmsManager&lt;/code&gt; was a bit trickier but we ended up figuring out that there was a &lt;code&gt;android.telephony.gemini.GeminiSmsManager&lt;/code&gt; class that had the functionality.&lt;/p&gt;
+&lt;p&gt;In a different phone with a Mediatek SOC, this got renamed to &lt;code&gt;com.mediatek.telephony.gemini.SmsManager&lt;/code&gt; for some reason and dropped the &lt;code&gt;Gemini&lt;/code&gt; suffix only for the &lt;code&gt;SmsManager&lt;/code&gt;.&lt;/p&gt;
+&lt;h2 id=&#34;intel&#34;&gt;Intel&lt;/h2&gt;
+&lt;p&gt;It was also around this time that Intel started making SOCs for smartphones. We had an &lt;a href=&#34;https://www.gsmarena.com/asus_fonepad_7_%282014%29-6394.php&#34;&gt;ASUS Fonepad 7&lt;/a&gt;. Unlike with the Mediatek device, we didn&amp;rsquo;t have a library to use here and had to use reflection to find the hidden classes / methods.&lt;/p&gt;
+&lt;p&gt;What we found was that instead of having a single instance with every method taking a &lt;code&gt;sim&lt;/code&gt; parameter, they instead had separate instances of &lt;code&gt;TelephonyManager&lt;/code&gt; and &lt;code&gt;SmsManager&lt;/code&gt; for each SIM. You would call &lt;code&gt;TelephonyManager.get2ndTm()&lt;/code&gt; and &lt;code&gt;SmsManager.get2ndSmsManager()&lt;/code&gt; to have access to the 2nd SIM.&lt;/p&gt;
+&lt;h2 id=&#34;qualcomm&#34;&gt;Qualcomm&lt;/h2&gt;
+&lt;p&gt;The last phone I looked at was a &lt;a href=&#34;https://www.gsmarena.com/motorola_moto_g_dual_sim-5978.php&#34;&gt;dual-SIM Moto G&lt;/a&gt;. What&amp;rsquo;s interesting about this one is that the API completely changed in the upgrade from 4.4 to 5.0.&lt;/p&gt;
+&lt;p&gt;On Android 4.4, the API was pretty close to the Mediatek one. You had a single instance that could dispatch to other SIMs by having an extra parameter on all the methods. These were in &lt;code&gt;android.telephony.MSimTelephonyManager&lt;/code&gt; and &lt;code&gt;android.telephony.MSimSmsManager&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;On Android 5.0, the API was a weird mix of all the above and also the introduction of &lt;code&gt;android.telephony.SubscriptionManager&lt;/code&gt; which was quite close but not exactly the same as what ended up in the official API. Instead of &lt;code&gt;getActiveSubscriptionInfoList&lt;/code&gt; there was &lt;code&gt;getActiveSubIdList&lt;/code&gt; which only returned &lt;code&gt;long[]&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;For the information that would normally exist in &lt;code&gt;SubscriptionInfo&lt;/code&gt;, you had to query the main &lt;code&gt;TelephonyManager&lt;/code&gt; instance which had methods with an extra &lt;code&gt;long&lt;/code&gt; parameter for the subscription id. The &lt;code&gt;SmsManager&lt;/code&gt; was simpler with just &lt;code&gt;getSmsManagerForSubscriber&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;With Android 5.1, I assume they just switched to using the official API so this phone would have gone through 3 different multi-SIM APIs over the course of it&amp;rsquo;s life.&lt;/p&gt;
+&lt;h2 id=&#34;epilogue&#34;&gt;Epilogue&lt;/h2&gt;
+&lt;p&gt;Around the release of Android 5.1, we stopped work on the app so I never actually got to use the official API myself ironically. We also never really got a big deployment so while I saw quite the variety of multi-SIM implementations, that&amp;rsquo;s probably not all that&amp;rsquo;s been out in the wild.&lt;/p&gt;
+</content:encoded>
+    </item>
+    
     <item>
       <title>ISP Issues</title>
       <link>https://pleasantprogrammer.com/posts/isp-issues.html</link>

+ 31 - 1
output/rss.xml

@@ -6,11 +6,41 @@
     <description>Recent content on Pleasant Programmer</description>
     <generator>Hugo -- gohugo.io</generator>
     <language>en-us</language>
-    <lastBuildDate>Thu, 16 Aug 2018 23:03:05 +0900</lastBuildDate>
+    <lastBuildDate>Sun, 12 Sep 2021 19:37:22 +0900</lastBuildDate>
     
 	<atom:link href="https://pleasantprogrammer.com/rss.xml" rel="self" type="application/rss+xml" />
     
     
+    <item>
+      <title>Android Multisim Pre-5.1</title>
+      <link>https://pleasantprogrammer.com/posts/android-multisim.html</link>
+      <pubDate>Sun, 12 Sep 2021 19:37:22 +0900</pubDate>
+      
+      <guid>https://pleasantprogrammer.com/posts/android-multisim.html</guid>
+      <description>NOTE if you&amp;rsquo;re just looking for a library to use, there&amp;rsquo;s MultiSim. I&amp;rsquo;ve never used this so I can&amp;rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.
+Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.</description>
+      <content:encoded>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; if you&amp;rsquo;re just looking for a library to use, there&amp;rsquo;s &lt;a href=&#34;https://github.com/UseHover/MultiSim&#34;&gt;MultiSim&lt;/a&gt;. I&amp;rsquo;ve never used this so I can&amp;rsquo;t guarantee anything about it. It also only supports SIM information and not SMS.&lt;/p&gt;
+&lt;p&gt;Phones that can take multiple SIM cards are quite popular in the Philippines. The two major telecoms would have unlimited SMS packages for messages within their networks. It was quite common to have a SIM for each telco and use the appropriate one depending on who you were sending to.&lt;/p&gt;
+&lt;p&gt;Android&amp;rsquo;s API only officially supported multiple SIM cards in 5.1 (API level 22) but Android phones with dual-SIM (and even triple-SIM) capabilities were already available at least as far back as 2.3 (API level 10) when I first needed to support it. Since there was no official API for this, the manufacturers just invented their own and of course each one implemented it in a different way.&lt;/p&gt;
+&lt;h2 id=&#34;mediatek&#34;&gt;Mediatek&lt;/h2&gt;
+&lt;p&gt;The first phone we started working on was a &lt;a href=&#34;https://www.gsmarena.com/lenovo_a60-4711.php&#34;&gt;Lenovo A60&lt;/a&gt; which used a Mediatek SOC. We somehow got a library from the manufacturer that let us use the dual-SIM functionality, but it was quite a pain to get working as there was limited documentation and we were quite new to Android development at the time.&lt;/p&gt;
+&lt;p&gt;When we disassembled the library that they gave us, we noticed that the names they used for the additional functions were quite interesting. They were all the &lt;code&gt;TelephonyManager&lt;/code&gt; and &lt;code&gt;SmsManager&lt;/code&gt; methods with a &lt;code&gt;Gemini&lt;/code&gt; suffix and they would take an additional &lt;code&gt;int&lt;/code&gt; parameter in addition to the original.&lt;/p&gt;
+&lt;p&gt;It turned out that these were available on the standard &lt;code&gt;TelephonyManager&lt;/code&gt; instance and could be accessed via reflection. The &lt;code&gt;SmsManager&lt;/code&gt; was a bit trickier but we ended up figuring out that there was a &lt;code&gt;android.telephony.gemini.GeminiSmsManager&lt;/code&gt; class that had the functionality.&lt;/p&gt;
+&lt;p&gt;In a different phone with a Mediatek SOC, this got renamed to &lt;code&gt;com.mediatek.telephony.gemini.SmsManager&lt;/code&gt; for some reason and dropped the &lt;code&gt;Gemini&lt;/code&gt; suffix only for the &lt;code&gt;SmsManager&lt;/code&gt;.&lt;/p&gt;
+&lt;h2 id=&#34;intel&#34;&gt;Intel&lt;/h2&gt;
+&lt;p&gt;It was also around this time that Intel started making SOCs for smartphones. We had an &lt;a href=&#34;https://www.gsmarena.com/asus_fonepad_7_%282014%29-6394.php&#34;&gt;ASUS Fonepad 7&lt;/a&gt;. Unlike with the Mediatek device, we didn&amp;rsquo;t have a library to use here and had to use reflection to find the hidden classes / methods.&lt;/p&gt;
+&lt;p&gt;What we found was that instead of having a single instance with every method taking a &lt;code&gt;sim&lt;/code&gt; parameter, they instead had separate instances of &lt;code&gt;TelephonyManager&lt;/code&gt; and &lt;code&gt;SmsManager&lt;/code&gt; for each SIM. You would call &lt;code&gt;TelephonyManager.get2ndTm()&lt;/code&gt; and &lt;code&gt;SmsManager.get2ndSmsManager()&lt;/code&gt; to have access to the 2nd SIM.&lt;/p&gt;
+&lt;h2 id=&#34;qualcomm&#34;&gt;Qualcomm&lt;/h2&gt;
+&lt;p&gt;The last phone I looked at was a &lt;a href=&#34;https://www.gsmarena.com/motorola_moto_g_dual_sim-5978.php&#34;&gt;dual-SIM Moto G&lt;/a&gt;. What&amp;rsquo;s interesting about this one is that the API completely changed in the upgrade from 4.4 to 5.0.&lt;/p&gt;
+&lt;p&gt;On Android 4.4, the API was pretty close to the Mediatek one. You had a single instance that could dispatch to other SIMs by having an extra parameter on all the methods. These were in &lt;code&gt;android.telephony.MSimTelephonyManager&lt;/code&gt; and &lt;code&gt;android.telephony.MSimSmsManager&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;On Android 5.0, the API was a weird mix of all the above and also the introduction of &lt;code&gt;android.telephony.SubscriptionManager&lt;/code&gt; which was quite close but not exactly the same as what ended up in the official API. Instead of &lt;code&gt;getActiveSubscriptionInfoList&lt;/code&gt; there was &lt;code&gt;getActiveSubIdList&lt;/code&gt; which only returned &lt;code&gt;long[]&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;For the information that would normally exist in &lt;code&gt;SubscriptionInfo&lt;/code&gt;, you had to query the main &lt;code&gt;TelephonyManager&lt;/code&gt; instance which had methods with an extra &lt;code&gt;long&lt;/code&gt; parameter for the subscription id. The &lt;code&gt;SmsManager&lt;/code&gt; was simpler with just &lt;code&gt;getSmsManagerForSubscriber&lt;/code&gt;.&lt;/p&gt;
+&lt;p&gt;With Android 5.1, I assume they just switched to using the official API so this phone would have gone through 3 different multi-SIM APIs over the course of it&amp;rsquo;s life.&lt;/p&gt;
+&lt;h2 id=&#34;epilogue&#34;&gt;Epilogue&lt;/h2&gt;
+&lt;p&gt;Around the release of Android 5.1, we stopped work on the app so I never actually got to use the official API myself ironically. We also never really got a big deployment so while I saw quite the variety of multi-SIM implementations, that&amp;rsquo;s probably not all that&amp;rsquo;s been out in the wild.&lt;/p&gt;
+</content:encoded>
+    </item>
+    
     <item>
       <title>ISP Issues</title>
       <link>https://pleasantprogrammer.com/posts/isp-issues.html</link>

+ 15 - 9
output/sitemap.xml

@@ -2,19 +2,28 @@
 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
   xmlns:xhtml="http://www.w3.org/1999/xhtml">
   <url>
-    <loc>https://pleasantprogrammer.com/posts/isp-issues.html</loc>
-    <lastmod>2018-08-16T23:03:05+09:00</lastmod>
+    <loc>https://pleasantprogrammer.com/tags/android.html</loc>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
+  </url><url>
+    <loc>https://pleasantprogrammer.com/posts/android-multisim.html</loc>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
   </url><url>
     <loc>https://pleasantprogrammer.com/</loc>
-    <lastmod>2018-08-16T23:03:05+09:00</lastmod>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
   </url><url>
     <loc>https://pleasantprogrammer.com/posts.html</loc>
-    <lastmod>2018-08-16T23:03:05+09:00</lastmod>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
   </url><url>
-    <loc>https://pleasantprogrammer.com/tags/sysadmin.html</loc>
-    <lastmod>2018-08-16T23:03:05+09:00</lastmod>
+    <loc>https://pleasantprogrammer.com/tags/programming.html</loc>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
   </url><url>
     <loc>https://pleasantprogrammer.com/tags.html</loc>
+    <lastmod>2021-09-12T19:37:22+09:00</lastmod>
+  </url><url>
+    <loc>https://pleasantprogrammer.com/posts/isp-issues.html</loc>
+    <lastmod>2018-08-16T23:03:05+09:00</lastmod>
+  </url><url>
+    <loc>https://pleasantprogrammer.com/tags/sysadmin.html</loc>
     <lastmod>2018-08-16T23:03:05+09:00</lastmod>
   </url><url>
     <loc>https://pleasantprogrammer.com/pages.html</loc>
@@ -28,9 +37,6 @@
   </url><url>
     <loc>https://pleasantprogrammer.com/tags/games.html</loc>
     <lastmod>2017-11-19T22:00:00+08:00</lastmod>
-  </url><url>
-    <loc>https://pleasantprogrammer.com/tags/programming.html</loc>
-    <lastmod>2017-11-19T22:00:00+08:00</lastmod>
   </url><url>
     <loc>https://pleasantprogrammer.com/tags/bluetooth.html</loc>
     <lastmod>2017-01-15T19:31:00+08:00</lastmod>

+ 3 - 1
output/tags.html

@@ -42,6 +42,8 @@
 	<ul class="postlist">
 		
 		
+		<li><a class="reference listtitle" href="/tags/android.html">android</a> (1)</li>
+		
 		<li><a class="reference listtitle" href="/tags/bluetooth.html">bluetooth</a> (1)</li>
 		
 		<li><a class="reference listtitle" href="/tags/cloudflare.html">cloudflare</a> (1)</li>
@@ -56,7 +58,7 @@
 		
 		<li><a class="reference listtitle" href="/tags/philippine-transit-app.html">philippine-transit-app</a> (12)</li>
 		
-		<li><a class="reference listtitle" href="/tags/programming.html">programming</a> (14)</li>
+		<li><a class="reference listtitle" href="/tags/programming.html">programming</a> (15)</li>
 		
 		<li><a class="reference listtitle" href="/tags/sysadmin.html">sysadmin</a> (6)</li>