Add /cards
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package im.angry.openeuicc.bridge;
|
package im.angry.openeuicc.bridge;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -20,9 +22,12 @@ import android.database.MatrixCursor;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import im.angry.openeuicc.OpenEuiccApplication;
|
import im.angry.openeuicc.OpenEuiccApplication;
|
||||||
|
import im.angry.openeuicc.core.DefaultEuiccChannelManager;
|
||||||
import im.angry.openeuicc.core.EuiccChannel;
|
import im.angry.openeuicc.core.EuiccChannel;
|
||||||
import im.angry.openeuicc.core.EuiccChannelManager;
|
import im.angry.openeuicc.core.EuiccChannelManager;
|
||||||
import im.angry.openeuicc.util.LPAUtilsKt;
|
import im.angry.openeuicc.util.LPAUtilsKt;
|
||||||
|
import im.angry.openeuicc.util.UiccCardInfoCompat;
|
||||||
|
import im.angry.openeuicc.util.UiccPortInfoCompat;
|
||||||
import im.angry.openeuicc.di.AppContainer;
|
import im.angry.openeuicc.di.AppContainer;
|
||||||
import net.typeblog.lpac_jni.LocalProfileInfo;
|
import net.typeblog.lpac_jni.LocalProfileInfo;
|
||||||
|
|
||||||
@@ -33,7 +38,7 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCreate()
|
public boolean onCreate()
|
||||||
{
|
{
|
||||||
appContainer = ((OpenEuiccApplication)getContext().getApplicationContext()).getAppContainer();
|
appContainer = ((OpenEuiccApplication) getContext().getApplicationContext()).getAppContainer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +64,9 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
case "ping":
|
case "ping":
|
||||||
rows = handlePing(args);
|
rows = handlePing(args);
|
||||||
break;
|
break;
|
||||||
|
case "cards":
|
||||||
|
rows = handleGetCards(args);
|
||||||
|
break;
|
||||||
case "profiles":
|
case "profiles":
|
||||||
rows = handleGetProfiles(args);
|
rows = handleGetProfiles(args);
|
||||||
break;
|
break;
|
||||||
@@ -99,30 +107,84 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
return row("ping", "pong");
|
return row("ping", "pong");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MatrixCursor handleGetCards(Map<String, String> args) throws Exception
|
||||||
|
{
|
||||||
|
var euiccChannelManager = (DefaultEuiccChannelManager) appContainer.getEuiccChannelManager();
|
||||||
|
|
||||||
|
var getUiccCardsMethod = DefaultEuiccChannelManager.class.getDeclaredMethod("getUiccCards");
|
||||||
|
getUiccCardsMethod.setAccessible(true);
|
||||||
|
|
||||||
|
var findEuiccChannelByPortMethod = DefaultEuiccChannelManager.class.getDeclaredMethod("findEuiccChannelByPort", int.class, int.class, Continuation.class);
|
||||||
|
findEuiccChannelByPortMethod.setAccessible(true);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
var cards = (Collection<UiccCardInfoCompat>) getUiccCardsMethod.invoke(euiccChannelManager);
|
||||||
|
|
||||||
|
var rows = new MatrixCursor(new String[]
|
||||||
|
{
|
||||||
|
"slotId",
|
||||||
|
"portId"
|
||||||
|
});
|
||||||
|
|
||||||
|
for (UiccCardInfoCompat card : cards)
|
||||||
|
{
|
||||||
|
for (UiccPortInfoCompat port : card.getPorts())
|
||||||
|
{
|
||||||
|
int slotId = card.getPhysicalSlotIndex();
|
||||||
|
int portId = port.getPortIndex();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
var euiccChannel = (EuiccChannel) BuildersKt.runBlocking
|
||||||
|
(
|
||||||
|
EmptyCoroutineContext.INSTANCE,
|
||||||
|
(_, continuation) ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return findEuiccChannelByPortMethod.invoke(euiccChannelManager, slotId, portId, continuation);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (euiccChannel != null)
|
||||||
|
{
|
||||||
|
rows.addRow(new Object[]
|
||||||
|
{
|
||||||
|
slotId,
|
||||||
|
portId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
private MatrixCursor handleGetProfiles(Map<String, String> args) throws Exception
|
private MatrixCursor handleGetProfiles(Map<String, String> args) throws Exception
|
||||||
{
|
{
|
||||||
List<LocalProfileInfo> profiles = withEuiccChannel(
|
List<LocalProfileInfo> profiles = withEuiccChannel
|
||||||
|
(
|
||||||
args,
|
args,
|
||||||
(channel, _) -> channel.getLpa().getProfiles()
|
(channel, _) -> channel.getLpa().getProfiles()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (profiles == null || profiles.isEmpty())
|
|
||||||
return empty();
|
|
||||||
|
|
||||||
var rows = new MatrixCursor(new String[]
|
var rows = new MatrixCursor(new String[]
|
||||||
{
|
{
|
||||||
"iccid",
|
"iccid",
|
||||||
"state",
|
"isEnabled",
|
||||||
"name",
|
"displayName"
|
||||||
"nickname"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (LocalProfileInfo profile : profiles)
|
for (LocalProfileInfo profile : profiles)
|
||||||
{
|
{
|
||||||
rows.addRow(new Object[] {
|
rows.addRow(new Object[]
|
||||||
|
{
|
||||||
profile.getIccid(),
|
profile.getIccid(),
|
||||||
profile.getState().toString(), // TODO: replace by LPAUtilsKt.isEnabled(profile)?
|
LPAUtilsKt.isEnabled(profile),
|
||||||
profile.getName(),
|
|
||||||
LPAUtilsKt.getDisplayName(profile)
|
LPAUtilsKt.getDisplayName(profile)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -134,29 +196,29 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
|
|
||||||
// region LPA Helpers
|
// region LPA Helpers
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private <T> T withEuiccChannel(Map<String, String> args, Function2<EuiccChannel, Continuation<? super T>, ?> operation) throws Exception
|
private <T> T withEuiccChannel(Map<String, String> args, Function2<EuiccChannel, Continuation<? super T>, ?> operation) throws Exception
|
||||||
{
|
{
|
||||||
final String slotIdArg = "slotId";
|
|
||||||
final String portIdArg = "portId";
|
|
||||||
|
|
||||||
var slotId = new int[1];
|
var slotId = new int[1];
|
||||||
var portId = new int[1];
|
var portId = new int[1];
|
||||||
|
requireSlotAndPort(args, slotId, portId);
|
||||||
|
|
||||||
if (!tryGetInt(args, slotIdArg, slotId))
|
return withEuiccChannel(slotId[0], portId[0], operation);
|
||||||
throw new Exception("missing_arg_" + slotIdArg);
|
}
|
||||||
|
|
||||||
if (!tryGetInt(args, portIdArg, portId))
|
@SuppressWarnings("unchecked")
|
||||||
throw new Exception("missing_arg_" + portIdArg);
|
private <T> T withEuiccChannel(int slotId, int portId, Function2<EuiccChannel, Continuation<? super T>, ?> operation) throws Exception
|
||||||
|
{
|
||||||
|
var euiccChannelManager = appContainer.getEuiccChannelManager();
|
||||||
|
|
||||||
EuiccChannelManager channelManager = appContainer.getEuiccChannelManager();
|
return (T) BuildersKt.runBlocking
|
||||||
|
(
|
||||||
return (T)BuildersKt.runBlocking(
|
|
||||||
EmptyCoroutineContext.INSTANCE,
|
EmptyCoroutineContext.INSTANCE,
|
||||||
(scope, continuation) -> {
|
(scope, continuation) ->
|
||||||
return channelManager.withEuiccChannel(
|
{
|
||||||
slotId[0],
|
return euiccChannelManager.withEuiccChannel
|
||||||
portId[0],
|
(
|
||||||
|
slotId,
|
||||||
|
portId,
|
||||||
operation,
|
operation,
|
||||||
continuation
|
continuation
|
||||||
);
|
);
|
||||||
@@ -168,16 +230,17 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
|
|
||||||
// region Arg Helpers
|
// region Arg Helpers
|
||||||
|
|
||||||
|
// TODO: decode?
|
||||||
private static Map<String, String> getArgsFromUri(Uri uri)
|
private static Map<String, String> getArgsFromUri(Uri uri)
|
||||||
{
|
{
|
||||||
var out = new HashMap<String, String>();
|
var args = new HashMap<String, String>();
|
||||||
|
|
||||||
for (String name : uri.getQueryParameterNames())
|
for (String name : uri.getQueryParameterNames())
|
||||||
{
|
{
|
||||||
out.put(name, uri.getQueryParameter(name));
|
args.put(name, uri.getQueryParameter(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean tryGet(Map<String, String> args, String key, String[] out)
|
private static boolean tryGet(Map<String, String> args, String key, String[] out)
|
||||||
@@ -193,14 +256,14 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
|
|
||||||
private static boolean tryGetInt(Map<String, String> args, String key, int[] out)
|
private static boolean tryGetInt(Map<String, String> args, String key, int[] out)
|
||||||
{
|
{
|
||||||
String[] tmp = new String[1];
|
String[] arg = new String[1];
|
||||||
|
|
||||||
if (!tryGet(args, key, tmp))
|
if (!tryGet(args, key, arg))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out[0] = Integer.parseInt(tmp[0]);
|
out[0] = Integer.parseInt(arg[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (NumberFormatException ex)
|
catch (NumberFormatException ex)
|
||||||
@@ -209,6 +272,18 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requireSlotAndPort(Map<String, String> args, int[] slotIdOut, int[] portIdOut) throws Exception
|
||||||
|
{
|
||||||
|
final String slotIdArg = "slotId";
|
||||||
|
final String portIdArg = "portId";
|
||||||
|
|
||||||
|
if (!tryGetInt(args, slotIdArg, slotIdOut))
|
||||||
|
throw new Exception("missing_arg_" + slotIdArg);
|
||||||
|
|
||||||
|
if (!tryGetInt(args, portIdArg, portIdOut))
|
||||||
|
throw new Exception("missing_arg_" + portIdArg);
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Row Helpers
|
// region Row Helpers
|
||||||
@@ -220,9 +295,9 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MatrixCursor row(String key, String value)
|
private static MatrixCursor row(String column, String value)
|
||||||
{
|
{
|
||||||
return rows(new String[] { key }, value);
|
return rows(new String[] { column }, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MatrixCursor error(String message)
|
private static MatrixCursor error(String message)
|
||||||
@@ -235,36 +310,30 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
return new MatrixCursor(new String[0]);
|
return new MatrixCursor(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MatrixCursor projectColumns(MatrixCursor source, String[] projection)
|
private static MatrixCursor projectColumns(MatrixCursor rows, String[] projection)
|
||||||
{
|
{
|
||||||
return projectColumns(source, projection, null);
|
return projectColumns(rows, projection, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MatrixCursor projectColumns(MatrixCursor source, String[] projection, String[] preserve)
|
private static MatrixCursor projectColumns(MatrixCursor rows, String[] projection, String[] preserve)
|
||||||
{
|
{
|
||||||
if (source == null)
|
String[] rowCols = rows.getColumnNames();
|
||||||
return empty();
|
|
||||||
|
|
||||||
String[] sourceCols = source.getColumnNames();
|
|
||||||
var cols = new LinkedHashSet<String>();
|
var cols = new LinkedHashSet<String>();
|
||||||
|
|
||||||
if (projection != null && projection.length > 0)
|
if (projection != null && projection.length > 0)
|
||||||
Collections.addAll(cols, projection);
|
Collections.addAll(cols, projection);
|
||||||
else
|
else
|
||||||
Collections.addAll(cols, sourceCols);
|
Collections.addAll(cols, rowCols);
|
||||||
|
|
||||||
if (preserve != null && preserve.length > 0)
|
if (preserve != null && preserve.length > 0)
|
||||||
{
|
{
|
||||||
for (String col : preserve)
|
for (String col : preserve)
|
||||||
{
|
{
|
||||||
if (col == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
boolean exists = false;
|
boolean exists = false;
|
||||||
|
|
||||||
for (String sourceCol : sourceCols)
|
for (String rowCol : rowCols)
|
||||||
{
|
{
|
||||||
if (col.equals(sourceCol))
|
if (col.equals(rowCol))
|
||||||
{
|
{
|
||||||
exists = true;
|
exists = true;
|
||||||
break;
|
break;
|
||||||
@@ -277,18 +346,18 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cols.isEmpty())
|
if (cols.isEmpty())
|
||||||
return source;
|
return rows;
|
||||||
|
|
||||||
var outCols = cols.toArray(new String[0]);
|
var outCols = cols.toArray(new String[0]);
|
||||||
var out = new MatrixCursor(outCols);
|
var outRows = new MatrixCursor(outCols);
|
||||||
|
|
||||||
while (source.moveToNext())
|
while (rows.moveToNext())
|
||||||
{
|
{
|
||||||
var row = new Object[outCols.length];
|
var row = new Object[outCols.length];
|
||||||
|
|
||||||
for (int i = 0; i < outCols.length; i++)
|
for (int i = 0; i < outCols.length; i++)
|
||||||
{
|
{
|
||||||
int index = source.getColumnIndex(outCols[i]);
|
int index = rows.getColumnIndex(outCols[i]);
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
@@ -296,31 +365,31 @@ public class LpaBridgeProvider extends ContentProvider
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (source.getType(index))
|
switch (rows.getType(index))
|
||||||
{
|
{
|
||||||
case Cursor.FIELD_TYPE_NULL:
|
case Cursor.FIELD_TYPE_NULL:
|
||||||
row[i] = null;
|
row[i] = null;
|
||||||
break;
|
break;
|
||||||
case Cursor.FIELD_TYPE_INTEGER:
|
case Cursor.FIELD_TYPE_INTEGER:
|
||||||
row[i] = source.getLong(index);
|
row[i] = rows.getLong(index);
|
||||||
break;
|
break;
|
||||||
case Cursor.FIELD_TYPE_FLOAT:
|
case Cursor.FIELD_TYPE_FLOAT:
|
||||||
row[i] = source.getDouble(index);
|
row[i] = rows.getDouble(index);
|
||||||
break;
|
break;
|
||||||
case Cursor.FIELD_TYPE_BLOB:
|
case Cursor.FIELD_TYPE_BLOB:
|
||||||
row[i] = source.getBlob(index);
|
row[i] = rows.getBlob(index);
|
||||||
break;
|
break;
|
||||||
case Cursor.FIELD_TYPE_STRING:
|
case Cursor.FIELD_TYPE_STRING:
|
||||||
default:
|
default:
|
||||||
row[i] = source.getString(index);
|
row[i] = rows.getString(index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.addRow(row);
|
outRows.addRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return outRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user