Explorar el Código

add project

master
xiaohanzi hace 3 años
commit
03b4c5d187
Se han modificado 100 ficheros con 6056 adiciones y 0 borrados
  1. +20
    -0
      .gitignore
  2. +1
    -0
      andlinker/.gitignore
  3. +58
    -0
      andlinker/bintray.gradle
  4. +29
    -0
      andlinker/build.gradle
  5. +44
    -0
      andlinker/install.gradle
  6. +29
    -0
      andlinker/proguard-rules.pro
  7. +23
    -0
      andlinker/properties.gradle
  8. +2
    -0
      andlinker/src/main/AndroidManifest.xml
  9. +295
    -0
      andlinker/src/main/java/com/codezjx/andlinker/AndLinker.java
  10. +38
    -0
      andlinker/src/main/java/com/codezjx/andlinker/AndLinkerBinder.java
  11. +356
    -0
      andlinker/src/main/java/com/codezjx/andlinker/ArrayType.java
  12. +44
    -0
      andlinker/src/main/java/com/codezjx/andlinker/BaseTypeWrapper.java
  13. +34
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Call.java
  14. +36
    -0
      andlinker/src/main/java/com/codezjx/andlinker/CallAdapter.java
  15. +19
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Callback.java
  16. +60
    -0
      andlinker/src/main/java/com/codezjx/andlinker/CallbackTypeWrapper.java
  17. +49
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Dispatcher.java
  18. +114
    -0
      andlinker/src/main/java/com/codezjx/andlinker/ICallback.java
  19. +184
    -0
      andlinker/src/main/java/com/codezjx/andlinker/ITransfer.java
  20. +65
    -0
      andlinker/src/main/java/com/codezjx/andlinker/InOutTypeWrapper.java
  21. +67
    -0
      andlinker/src/main/java/com/codezjx/andlinker/InTypeWrapper.java
  22. +197
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Invoker.java
  23. +58
    -0
      andlinker/src/main/java/com/codezjx/andlinker/LinkerBinderImpl.java
  24. +127
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Logger.java
  25. +50
    -0
      andlinker/src/main/java/com/codezjx/andlinker/MethodExecutor.java
  26. +109
    -0
      andlinker/src/main/java/com/codezjx/andlinker/OutType.java
  27. +95
    -0
      andlinker/src/main/java/com/codezjx/andlinker/OutTypeWrapper.java
  28. +80
    -0
      andlinker/src/main/java/com/codezjx/andlinker/ParameterHandler.java
  29. +131
    -0
      andlinker/src/main/java/com/codezjx/andlinker/RemoteCall.java
  30. +134
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Request.java
  31. +31
    -0
      andlinker/src/main/java/com/codezjx/andlinker/RequestBuilder.java
  32. +80
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Response.java
  33. +159
    -0
      andlinker/src/main/java/com/codezjx/andlinker/ServiceMethod.java
  34. +17
    -0
      andlinker/src/main/java/com/codezjx/andlinker/SuperParcelable.java
  35. +166
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Type.java
  36. +30
    -0
      andlinker/src/main/java/com/codezjx/andlinker/TypeFactory.java
  37. +227
    -0
      andlinker/src/main/java/com/codezjx/andlinker/Utils.java
  38. +27
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/DefaultCallAdapterFactory.java
  39. +125
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/OriginalCallAdapterFactory.java
  40. +163
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/CallArbiter.java
  41. +36
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/CallExecuteOnSubscribe.java
  42. +35
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/RxJavaCallAdapter.java
  43. +47
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/RxJavaCallAdapterFactory.java
  44. +66
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/CallExecuteObservable.java
  45. +38
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/RxJava2CallAdapter.java
  46. +50
    -0
      andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/RxJava2CallAdapterFactory.java
  47. +16
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/Callback.java
  48. +16
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/In.java
  49. +16
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/Inout.java
  50. +17
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/OneWay.java
  51. +16
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/Out.java
  52. +16
    -0
      andlinker/src/main/java/com/codezjx/andlinker/annotation/RemoteInterface.java
  53. +1
    -0
      app/.gitignore
  54. +80
    -0
      app/build.gradle
  55. BIN
      app/libs/WTAndroidJar.jar
  56. BIN
      app/libs/armeabi/libjni.so
  57. BIN
      app/libs/armeabi/libusb.so
  58. BIN
      app/libs/butterknife-7.0.1.jar
  59. BIN
      app/libs/eventbus-3.0.0.jar
  60. BIN
      app/libs/litepal-1.3.0-src.jar
  61. BIN
      app/libs/printer.jar
  62. BIN
      app/libs/printer_library.jar
  63. BIN
      app/libs/rtdriver.jar
  64. BIN
      app/libs/screenlib.jar
  65. BIN
      app/libs_ext/androidsim.jar
  66. +17
    -0
      app/proguard-rules.pro
  67. +13
    -0
      app/src/androidTest/java/com/neusoft/possale/ApplicationTest.java
  68. +266
    -0
      app/src/main/AndroidManifest.xml
  69. +3
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CandidateAppInfo.aidl
  70. +133
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CandidateAppInfo.java
  71. +52
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CheckCardListener.aidl
  72. +14
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/FontFamily.java
  73. +21
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IBeeper.aidl
  74. +102
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IDeviceInfo.aidl
  75. +88
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IDeviceService.aidl
  76. +43
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IInsertCardReader.aidl
  77. +31
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ILed.aidl
  78. +21
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IMagCardReader.aidl
  79. +213
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPBOC.aidl
  80. +113
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPinpad.aidl
  81. +105
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPrinter.aidl
  82. +127
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IRFCardReader.aidl
  83. +25
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IScanner.aidl
  84. +75
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ISerialPort.aidl
  85. +38
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/MagCardListener.aidl
  86. +30
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/OnlineResultHandler.aidl
  87. +100
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PBOCHandler.aidl
  88. +32
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PinInputListener.aidl
  89. +16
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PinpadKeyType.java
  90. +10
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PrinterConfig.java
  91. +18
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PrinterListener.aidl
  92. +37
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/RFSearchListener.aidl
  93. +30
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ScannerListener.aidl
  94. +3
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/TusnData.aidl
  95. +75
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/TusnData.java
  96. +35
    -0
      app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/UPCardListener.aidl
  97. +15
    -0
      app/src/main/aidl/com/icbc/smartpos/transservice/aidl/ITransService.aidl
  98. +10
    -0
      app/src/main/aidl/com/icbc/smartpos/transservice/aidl/TransHandler.aidl
  99. +115
    -0
      app/src/main/aidl/com/unionpay/CloudPosPaymentClient/aidl/ICloudPay.aidl
  100. +7
    -0
      app/src/main/aidl/com/unionpay/facepay/IFacePayInterface.aidl

+ 20
- 0
.gitignore Ver fichero

@@ -0,0 +1,20 @@
gen/
bin/
Thumbs.db
proguard/dump.txt
proguard/mapping.txt
proguard/seeds.txt
proguard/usage.txt
log.txt
.idea/
*.iml

.gradle/
build/
proguard/
local.properties
gradle.properties

gradle/
gradlew
gradlew.bat

+ 1
- 0
andlinker/.gitignore Ver fichero

@@ -0,0 +1 @@
/build

+ 58
- 0
andlinker/bintray.gradle Ver fichero

@@ -0,0 +1,58 @@
apply plugin: 'com.jfrog.bintray'

version = libraryVersion

if (project.hasProperty("android")) { // Android libraries
task sourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
} else { // Java libraries
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives javadocJar
archives sourcesJar
}

// Bintray
Properties properties = new Properties()
properties.load(project.rootProject.file('gradle.properties').newDataInputStream())

bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")

configurations = ['archives']
pkg {
repo = bintrayRepo
name = bintrayName
desc = libraryDescription
websiteUrl = siteUrl
vcsUrl = gitUrl
licenses = allLicenses
publish = true
publicDownloadNumbers = true
version {
desc = libraryDescription
gpg {
sign = true //Determines whether to GPG sign the files. The default is false
passphrase = properties.getProperty("bintray.gpg.password") //Optional. The passphrase for GPG signing'
}
}
}
}

+ 29
- 0
andlinker/build.gradle Ver fichero

@@ -0,0 +1,29 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion versions.compileSdk

defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 1
versionName "1.0"
}

buildTypes {
release {
minifyEnabled false
consumerProguardFiles 'proguard-rules.pro'
}
}

}

dependencies {
compileOnly deps.rx.java
compileOnly deps.rx.java2
}

apply from: 'properties.gradle'
apply from: 'install.gradle'
apply from: 'bintray.gradle'

+ 44
- 0
andlinker/install.gradle Ver fichero

@@ -0,0 +1,44 @@
apply plugin: 'com.github.dcendents.android-maven'

// Maven Group ID for the artifact
group = publishedGroupId

install {
repositories.mavenInstaller {
// This generates POM.xml with proper parameters
pom {
project {
packaging 'aar'
groupId publishedGroupId
artifactId artifact

// Add your description here
name libraryName
description libraryDescription
url siteUrl

// Set your license
licenses {
license {
name licenseName
url licenseUrl
}
}
developers {
developer {
id developerId
name developerName
email developerEmail
}
}
scm {
connection gitUrl
developerConnection gitUrl
url siteUrl
}
}
}
}
}

+ 29
- 0
andlinker/proguard-rules.pro Ver fichero

@@ -0,0 +1,29 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-dontwarn com.codezjx.andlinker.adapter.**
-keep class * implements com.codezjx.andlinker.SuperParcelable {
public void readFromParcel(android.os.Parcel);
}
-keep @com.codezjx.andlinker.annotation.RemoteInterface class * {
<methods>;
}

+ 23
- 0
andlinker/properties.gradle Ver fichero

@@ -0,0 +1,23 @@
ext {
bintrayRepo = 'maven'
bintrayName = 'and-linker'

publishedGroupId = 'com.codezjx.library'
libraryName = 'AndLinker'
artifact = 'andlinker'

libraryDescription = 'AndLinker is a IPC library for Android, which combines the features of AIDL and Retrofit. Allows IPC call seamlessly compose with rxjava and rxjava2 call adapters.'

siteUrl = 'https://github.com/codezjx/AndLinker'
gitUrl = 'https://github.com/codezjx/AndLinker.git'

libraryVersion = '0.7.1'

developerId = 'codezjx'
developerName = 'codezjx'
developerEmail = 'code.zjx@gmail.com'

licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
}

+ 2
- 0
andlinker/src/main/AndroidManifest.xml Ver fichero

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.codezjx.andlinker"/>

+ 295
- 0
andlinker/src/main/java/com/codezjx/andlinker/AndLinker.java Ver fichero

@@ -0,0 +1,295 @@
package com.codezjx.andlinker;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;

import com.codezjx.andlinker.adapter.DefaultCallAdapterFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.codezjx.andlinker.Utils.checkNotNull;

/**
* AndLinker adapts a Java interface to IPC calls by using annotations on the declared methods to
* define how requests are made. Create instances using {@linkplain Builder
* the builder} and pass your interface to {@link #create} to generate an implementation.
*/
public final class AndLinker {
private static final String TAG = "AndLinker";

private final Map<Method, ServiceMethod> serviceMethodCache = new ConcurrentHashMap<>();
private ServiceConnection mServiceConnection;
private Invoker mInvoker;
private Context mContext;
private String mPackageName;
private String mAction;
private String mClassName;
private List<CallAdapter.Factory> mAdapterFactories;
private Dispatcher mDispatcher;
private ITransfer mTransferService;
private ICallback mCallback;
private BindCallback mBindCallback;
private AndLinker(Context context, String packageName, String action, String className, List<CallAdapter.Factory> adapterFactories) {
mContext = context;
mPackageName = packageName;
mAction = action;
mClassName = className;
mInvoker = new Invoker();
mAdapterFactories = adapterFactories;
mDispatcher = new Dispatcher();
mServiceConnection = createServiceConnection();
mCallback = createCallback();
}

/**
* Create an implementation defined by the remote service interface.
*/
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
RemoteCall remoteCall = new RemoteCall(mTransferService, serviceMethod, args, mDispatcher);
return serviceMethod.getCallAdapter().adapt(remoteCall);
}
});
}

/**
* Connect to the remote service.
*/
public void bind() {
Intent intent = new Intent();
if (!Utils.isStringBlank(mAction)) {
intent.setAction(mAction);
} else if (!Utils.isStringBlank(mClassName)) {
intent.setClassName(mPackageName, mClassName);
}
// After android 5.0+, service Intent must be explicit.
intent.setPackage(mPackageName);
mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

/**
* Disconnect from the remote service.
*/
public void unbind() {
mContext.unbindService(mServiceConnection);
}

/**
* Register client interface implementation called by remote service.
*/
public void registerObject(Object target) {
mInvoker.registerObject(target);
}

/**
* Unregister client interface implementation.
*/
public void unRegisterObject(Object target) {
mInvoker.unRegisterObject(target);
}

/**
* Set callback to be invoked when linker is bind or unBind.
*/
public void setBindCallback(BindCallback bindCallback) {
mBindCallback = bindCallback;
}

/**
* Return the remote service bind state.
*/
public boolean isBind() {
return mTransferService != null;
}

CallAdapter<?, ?> findCallAdapter(Type returnType, Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
for (int i = 0, count = mAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = mAdapterFactories.get(i).get(returnType, annotations);
if (adapter != null) {
return adapter;
}
}

return DefaultCallAdapterFactory.INSTANCE.get(returnType, annotations);
}

private ServiceConnection createServiceConnection() {
return new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mTransferService = ITransfer.Stub.asInterface(service);
fireOnBind();
try {
mTransferService.register(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {
if (mTransferService == null) {
Logger.e(TAG, "Error occur, TransferService was null when service disconnected.");
fireOnUnBind();
return;
}
try {
mTransferService.unRegister(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
mTransferService = null;
fireOnUnBind();
}
};
}

private void fireOnBind() {
if (mBindCallback != null) {
mBindCallback.onBind();
}
}

private void fireOnUnBind() {
if (mBindCallback != null) {
mBindCallback.onUnBind();
}
}

private ICallback createCallback() {
return new ICallback.Stub() {
@Override
public Response callback(Request request) throws RemoteException {
Logger.d(TAG, "Receive callback in client:" + request.toString());
return mInvoker.invoke(request);
}
};
}
private ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result = serviceMethodCache.get(method);
if (result != null) {
return result;
}

synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}

/**
* Method to enable or disable internal logger
*/
public static void enableLogger(boolean enable) {
Logger.sEnable = enable;
}

/**
* Builder to create a new {@link AndLinker} instance.
*/
public static final class Builder {
private Context mContext;
private String mPackageName;
private String mAction;
private String mClassName;
private List<CallAdapter.Factory> mAdapterFactories = new ArrayList<>();
public Builder(Context context) {
mContext = context;
}

/**
* Set the remote service package name.
*/
public Builder packageName(String packageName) {
mPackageName = packageName;
return this;
}

/**
* Set the action to bind the remote service.
*/
public Builder action(String action) {
mAction = action;
return this;
}

/**
* Set the class name of the remote service.
*/
public Builder className(String className) {
mClassName = className;
return this;
}

/**
* Add a call adapter factory for supporting service method return types other than {@link Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
mAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}

/**
* Create the {@link AndLinker} instance using the configured values.
*/
public AndLinker build() {
if (Utils.isStringBlank(mPackageName)) {
throw new IllegalStateException("Package name required.");
}
if (Utils.isStringBlank(mAction) && Utils.isStringBlank(mClassName)) {
throw new IllegalStateException("You must set one of the action or className.");
}
return new AndLinker(mContext, mPackageName, mAction, mClassName, mAdapterFactories);
}
}

/**
* Interface definition for a callback to be invoked when linker is bind or unBind to the service.
*/
public interface BindCallback {

/**
* Called when a connection to the remote service has been established, now you can execute the remote call.
*/
void onBind();

/**
* Called when a connection to the remote service has been lost, any remote call will not execute.
*/
void onUnBind();
}
}

+ 38
- 0
andlinker/src/main/java/com/codezjx/andlinker/AndLinkerBinder.java Ver fichero

@@ -0,0 +1,38 @@
package com.codezjx.andlinker;

import android.os.IBinder;

/**
* AndLinker {@link IBinder} object to return in {@link android.app.Service#onBind(android.content.Intent)} method.
*/
public interface AndLinkerBinder extends IBinder {

/**
* Register service interface implementation.
*/
void registerObject(Object target);

/**
* Unregister service interface implementation.
*/
void unRegisterObject(Object target);

/**
* {@link AndLinkerBinder} factory class.
*/
final class Factory {

private Factory() {
}
/**
* Factory method to create the {@link AndLinkerBinder} impl instance.
*/
public static AndLinkerBinder newBinder() {
// Return inner package access LinkerBinder, prevent exposed.
return new LinkerBinderImpl();
}
}
}

+ 356
- 0
andlinker/src/main/java/com/codezjx/andlinker/ArrayType.java Ver fichero

@@ -0,0 +1,356 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.os.Parcelable;

import java.lang.reflect.Array;

/**
* Created by codezjx on 2017/11/28.<br/>
*/
interface ArrayType<T> extends OutType<T> {

T newInstance(int length);
final class ByteArrayType implements ArrayType<byte[]> {

@Override
public void writeToParcel(Parcel dest, int flags, byte[] val) {
dest.writeByteArray(val);
}

@Override
public byte[] createFromParcel(Parcel in) {
return in.createByteArray();
}

@Override
public void readFromParcel(Parcel in, byte[] val) {
in.readByteArray(val);
}

@Override
public byte[] newInstance(int length) {
return new byte[length];
}
}
final class ShortArrayType implements ArrayType<short[]> {

@Override
public void writeToParcel(Parcel dest, int flags, short[] val) {
if (val != null) {
int N = val.length;
dest.writeInt(N);
for (int i = 0; i < N; i++) {
dest.writeInt(val[i]);
}
} else {
dest.writeInt(-1);
}
}

@Override
public short[] createFromParcel(Parcel in) {
int N = in.readInt();
if (N >= 0 && N <= (in.dataAvail() >> 2)) {
short[] val = new short[N];
for (int i = 0; i < N; i++) {
val[i] = (short) in.readInt();
}
return val;
} else {
return null;
}
}

@Override
public void readFromParcel(Parcel in, short[] val) {
int N = in.readInt();
if (N == val.length) {
for (int i = 0; i < N; i++) {
val[i] = (short) in.readInt();
}
} else {
throw new RuntimeException("bad array lengths");
}
}

@Override
public short[] newInstance(int length) {
return new short[length];
}
}
final class IntArrayType implements ArrayType<int[]> {

@Override
public void writeToParcel(Parcel dest, int flags, int[] val) {
dest.writeIntArray(val);
}

@Override
public int[] createFromParcel(Parcel in) {
return in.createIntArray();
}

@Override
public void readFromParcel(Parcel in, int[] val) {
in.readIntArray(val);
}

@Override
public int[] newInstance(int length) {
return new int[length];
}
}
final class LongArrayType implements ArrayType<long[]> {

@Override
public void writeToParcel(Parcel dest, int flags, long[] val) {
dest.writeLongArray(val);
}

@Override
public long[] createFromParcel(Parcel in) {
return in.createLongArray();
}

@Override
public void readFromParcel(Parcel in, long[] val) {
in.readLongArray(val);
}

@Override
public long[] newInstance(int length) {
return new long[length];
}
}
final class FloatArrayType implements ArrayType<float[]> {

@Override
public void writeToParcel(Parcel dest, int flags, float[] val) {
dest.writeFloatArray(val);
}

@Override
public float[] createFromParcel(Parcel in) {
return in.createFloatArray();
}

@Override
public void readFromParcel(Parcel in, float[] val) {
in.readFloatArray(val);
}

@Override
public float[] newInstance(int length) {
return new float[length];
}
}
final class DoubleArrayType implements ArrayType<double[]> {

@Override
public void writeToParcel(Parcel dest, int flags, double[] val) {
dest.writeDoubleArray(val);
}

@Override
public double[] createFromParcel(Parcel in) {
return in.createDoubleArray();
}

@Override
public void readFromParcel(Parcel in, double[] val) {
in.readDoubleArray(val);
}

@Override
public double[] newInstance(int length) {
return new double[length];
}
}
final class BooleanArrayType implements ArrayType<boolean[]> {

@Override
public void writeToParcel(Parcel dest, int flags, boolean[] val) {
dest.writeBooleanArray(val);
}

@Override
public boolean[] createFromParcel(Parcel in) {
return in.createBooleanArray();
}

@Override
public void readFromParcel(Parcel in, boolean[] val) {
in.readBooleanArray(val);
}

@Override
public boolean[] newInstance(int length) {
return new boolean[length];
}
}
final class CharArrayType implements ArrayType<char[]> {

@Override
public void writeToParcel(Parcel dest, int flags, char[] val) {
dest.writeCharArray(val);
}

@Override
public char[] createFromParcel(Parcel in) {
return in.createCharArray();
}

@Override
public void readFromParcel(Parcel in, char[] val) {
in.readCharArray(val);
}

@Override
public char[] newInstance(int length) {
return new char[length];
}
}
final class StringArrayType implements ArrayType<String[]> {

@Override
public void writeToParcel(Parcel dest, int flags, String[] val) {
dest.writeStringArray(val);
}

@Override
public String[] createFromParcel(Parcel in) {
return in.createStringArray();
}

@Override
public void readFromParcel(Parcel in, String[] val) {
in.readStringArray(val);
}

@Override
public String[] newInstance(int length) {
return new String[length];
}
}
final class CharSequenceArrayType implements ArrayType<CharSequence[]> {

@Override
public void writeToParcel(Parcel dest, int flags, CharSequence[] val) {
writeCharSequenceArray(dest, val);
}

@Override
public CharSequence[] createFromParcel(Parcel in) {
return readCharSequenceArray(in);
}

@Override
public void readFromParcel(Parcel in, CharSequence[] val) {
int N = in.readInt();
if (N == val.length) {
for (int i = 0; i < N; i++) {
val[i] = Type.CharSequenceType.readCharSequence(in);
}
} else {
throw new RuntimeException("bad array lengths");
}
}

@Override
public CharSequence[] newInstance(int length) {
return new CharSequence[length];
}

private void writeCharSequenceArray(Parcel dest, CharSequence[] val) {
if (val != null) {
int N = val.length;
dest.writeInt(N);
for (int i = 0; i < N; i++) {
Type.CharSequenceType.writeCharSequence(dest, val[i]);
}
} else {
dest.writeInt(-1);
}
}

private CharSequence[] readCharSequenceArray(Parcel in) {
CharSequence[] array = null;

int length = in.readInt();
if (length >= 0) {
array = new CharSequence[length];

for (int i = 0 ; i < length ; i++) {
array[i] = Type.CharSequenceType.readCharSequence(in);
}
}

return array;
}
}

final class ParcelableArrayType implements ArrayType<Parcelable[]> {

@Override
public void writeToParcel(Parcel dest, int flags, Parcelable[] val) {
dest.writeString(val.getClass().getComponentType().getName());
dest.writeParcelableArray(val, flags);
}

@Override
public Parcelable[] createFromParcel(Parcel in) {
String componentType = in.readString();
Object obj = null;
try {
Class cls = Class.forName(componentType);
obj = createTypedArray(in, cls);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (Parcelable[]) obj;
}

@Override
public void readFromParcel(Parcel in, Parcelable[] val) {
// Just read and do nothing, because we don't need component type here
in.readString();
int N = in.readInt();
if (N == val.length) {
for (int i = 0; i < N; i++) {
val[i] = in.readParcelable(getClass().getClassLoader());
}
} else {
throw new RuntimeException("bad array lengths");
}
}

@Override
public Parcelable[] newInstance(int length) {
return new Parcelable[length];
}

private <T> T[] createTypedArray(Parcel in, Class<T> cls) {
int N = in.readInt();
if (N < 0) {
return null;
}
T[] arr = (T[]) Array.newInstance(cls, N);
for (int i = 0; i < N; i++) {
arr[i] = in.readParcelable(cls.getClassLoader());
}
return arr;
}
}
}

+ 44
- 0
andlinker/src/main/java/com/codezjx/andlinker/BaseTypeWrapper.java Ver fichero

@@ -0,0 +1,44 @@
package com.codezjx.andlinker;

/**
* Created by codezjx on 2017/11/19.<br/>
*/
interface BaseTypeWrapper extends SuperParcelable {

int TYPE_EMPTY = 0;
// Primitives
int TYPE_BYTE = 1;
int TYPE_SHORT = 2;
int TYPE_INT = 3;
int TYPE_LONG = 4;
int TYPE_FLOAT = 5;
int TYPE_DOUBLE = 6;
int TYPE_BOOLEAN = 7;
int TYPE_CHAR = 8;
// Primitive Arrays
int TYPE_BYTEARRAY = 9;
int TYPE_SHORTARRAY = 10;
int TYPE_INTARRAY = 11;
int TYPE_LONGARRAY = 12;
int TYPE_FLOATARRAY = 13;
int TYPE_DOUBLEARRAY = 14;
int TYPE_BOOLEANARRAY = 15;
int TYPE_CHARARRAY = 16;

// Other
int TYPE_STRING = 17;
int TYPE_STRINGARRAY = 18;
int TYPE_CHARSEQUENCE = 19;
int TYPE_CHARSEQUENCEARRAY = 20;
int TYPE_PARCELABLE = 21;
int TYPE_PARCELABLEARRAY = 22;
int TYPE_LIST = 23;
int TYPE_MAP = 24;
int TYPE_CALLBACK = 25;

int getType();

Object getParam();
}

+ 34
- 0
andlinker/src/main/java/com/codezjx/andlinker/Call.java Ver fichero

@@ -0,0 +1,34 @@
package com.codezjx.andlinker;

/**
* An invocation of a remote method that sends a request to host and returns a response.
*/
public interface Call<T> {
/**
* Synchronously send the request and return its response.
*/
T execute();

/**
* Asynchronously send the request and notify when response return.
* @param callback The callback to notify.
*/
void enqueue(Callback<T> callback);

/**
* Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain #enqueue(Callback) enqueued}.
*/
boolean isExecuted();

/**
* Cancel this call. If the call has not yet been executed it never will be.
*/
void cancel();

/**
* True if {@link #cancel()} was called.
*/
boolean isCanceled();
}

+ 36
- 0
andlinker/src/main/java/com/codezjx/andlinker/CallAdapter.java Ver fichero

@@ -0,0 +1,36 @@
package com.codezjx.andlinker;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

/**
* Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
* created by {@linkplain Factory factory} which is {@linkplain AndLinker.Builder#addCallAdapterFactory(Factory) installed}
* into the {@link AndLinker} instance.
*/
public interface CallAdapter<R, T> {
/**
* Returns an instance of {@code T} which delegates to {@code call}.
*/
T adapt(Call<R> call);

/**
* Creates {@link CallAdapter} instances based on the return type of {@linkplain
* AndLinker#create(Class) the service interface} methods.
*/
abstract class Factory {

/**
* Returns a call adapter for interface methods that return {@code returnType}, or null if it
* cannot be handled by this factory.
*/
public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations);

protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}

+ 19
- 0
andlinker/src/main/java/com/codezjx/andlinker/Callback.java Ver fichero

@@ -0,0 +1,19 @@
package com.codezjx.andlinker;

/**
* Interface definition for a callback to be invoked when execute {@linkplain Call#enqueue(Callback) asynchronously call}.
* By default callbacks are executed on the application's main (UI) thread.
*/
public interface Callback<T> {
/**
* Invoked for a received response.
*/
void onResponse(Call<T> call, T response);
/**
* Invoked when a remote exception occurred.
*/
void onFailure(Call<T> call, Throwable t);
}

+ 60
- 0
andlinker/src/main/java/com/codezjx/andlinker/CallbackTypeWrapper.java Ver fichero

@@ -0,0 +1,60 @@
package com.codezjx.andlinker;

import android.os.Parcel;

/**
* Created by codezjx on 2017/11/18.<br/>
*/
final class CallbackTypeWrapper implements BaseTypeWrapper {

private String mClassName;

CallbackTypeWrapper(String className) {
mClassName = className;
}

String getClassName() {
return mClassName;
}

@Override
public int getType() {
return TYPE_CALLBACK;
}

@Override
public Object getParam() {
return null;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mClassName);
}

@Override
public void readFromParcel(Parcel in) {
mClassName = in.readString();
}

private CallbackTypeWrapper(Parcel in) {
readFromParcel(in);
}

public static final Creator<CallbackTypeWrapper> CREATOR = new Creator<CallbackTypeWrapper>() {
@Override
public CallbackTypeWrapper createFromParcel(Parcel source) {
return new CallbackTypeWrapper(source);
}

@Override
public CallbackTypeWrapper[] newArray(int size) {
return new CallbackTypeWrapper[size];
}
};
}

+ 49
- 0
andlinker/src/main/java/com/codezjx/andlinker/Dispatcher.java Ver fichero

@@ -0,0 +1,49 @@
package com.codezjx.andlinker;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Created by codezjx on 2018/1/10.<br/>
*/
final class Dispatcher {

private static final String THREAD_NAME = "Dispatcher Thread #";
private static final int KEEP_ALIVE_TIME_SECONDS = 60;
private ExecutorService mExecutorService;

Dispatcher() {
}

Dispatcher(ExecutorService executorService) {
mExecutorService = executorService;
}

synchronized void enqueue(Runnable task) {
if (mExecutorService == null) {
mExecutorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), createFactory());
}
mExecutorService.execute(task);
}

private ThreadFactory createFactory() {
return new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, THREAD_NAME + mCount.getAndIncrement());
thread.setDaemon(false);
return thread;
}
};
}
}

+ 114
- 0
andlinker/src/main/java/com/codezjx/andlinker/ICallback.java Ver fichero

@@ -0,0 +1,114 @@
package com.codezjx.andlinker;

interface ICallback extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
abstract class Stub extends android.os.Binder implements ICallback {
private static final String DESCRIPTOR = "com.codezjx.alinker.ICallback";

/**
* Construct the stub at attach it to the interface.
*/
Stub() {
this.attachInterface(this, DESCRIPTOR);
}

/**
* Cast an IBinder object into an com.codezjx.alinker.ICallback interface,
* generating a proxy if needed.
*/
static ICallback asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof ICallback))) {
return ((ICallback) iin);
}
return new Proxy(obj);
}

@Override
public android.os.IBinder asBinder() {
return this;
}

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_callback: {
data.enforceInterface(DESCRIPTOR);
Request _arg0;
if ((0 != data.readInt())) {
_arg0 = Request.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
Response _result = this.callback(_arg0);
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements ICallback {
private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {
mRemote = remote;
}

@Override
public android.os.IBinder asBinder() {
return mRemote;
}

public String getInterfaceDescriptor() {
return DESCRIPTOR;
}

@Override
public Response callback(Request request) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
Response _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((request != null)) {
_data.writeInt(1);
request.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_callback, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = Response.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

static final int TRANSACTION_callback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}

Response callback(Request request) throws android.os.RemoteException;
}

+ 184
- 0
andlinker/src/main/java/com/codezjx/andlinker/ITransfer.java Ver fichero

@@ -0,0 +1,184 @@
package com.codezjx.andlinker;

interface ITransfer extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
abstract class Stub extends android.os.Binder implements ITransfer {
private static final String DESCRIPTOR = "com.codezjx.alinker.ITransfer";

/**
* Construct the stub at attach it to the interface.
*/
Stub() {
this.attachInterface(this, DESCRIPTOR);
}

/**
* Cast an IBinder object into an com.codezjx.alinker.ITransfer interface,
* generating a proxy if needed.
*/
static ITransfer asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof ITransfer))) {
return ((ITransfer) iin);
}
return new Proxy(obj);
}

@Override
public android.os.IBinder asBinder() {
return this;
}

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_execute: {
data.enforceInterface(DESCRIPTOR);
Request _arg0;
if ((0 != data.readInt())) {
_arg0 = Request.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
Response _result = this.execute(_arg0);
if ((flags & android.os.IBinder.FLAG_ONEWAY) != 0) {
// One-way mode just execute and return directly.
return true;
}
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
if ((_arg0 != null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_register: {
data.enforceInterface(DESCRIPTOR);
ICallback _arg0;
_arg0 = ICallback.Stub.asInterface(data.readStrongBinder());
this.register(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unRegister: {
data.enforceInterface(DESCRIPTOR);
ICallback _arg0;
_arg0 = ICallback.Stub.asInterface(data.readStrongBinder());
this.unRegister(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements ITransfer {
private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {
mRemote = remote;
}

@Override
public android.os.IBinder asBinder() {
return mRemote;
}

public String getInterfaceDescriptor() {
return DESCRIPTOR;
}

@Override
public Response execute(Request request) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
Response _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((request != null)) {
_data.writeInt(1);
request.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
// One-way mode just transact and return directly.
if (request != null && request.isOneWay()) {
mRemote.transact(Stub.TRANSACTION_execute, _data, null, android.os.IBinder.FLAG_ONEWAY);
return null;
}
mRemote.transact(Stub.TRANSACTION_execute, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = Response.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
if ((0 != _reply.readInt())) {
request.readFromParcel(_reply);
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

@Override
public void register(ICallback callback) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((callback != null)) ? (callback.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_register, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}

@Override
public void unRegister(ICallback callback) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((callback != null)) ? (callback.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_unRegister, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}

static final int TRANSACTION_execute = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_unRegister = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}

Response execute(Request request) throws android.os.RemoteException;

void register(ICallback callback) throws android.os.RemoteException;

void unRegister(ICallback callback) throws android.os.RemoteException;
}

+ 65
- 0
andlinker/src/main/java/com/codezjx/andlinker/InOutTypeWrapper.java Ver fichero

@@ -0,0 +1,65 @@
package com.codezjx.andlinker;

import android.os.Parcel;

/**
* Created by codezjx on 2017/11/30.<br/>
*/
final class InOutTypeWrapper implements BaseTypeWrapper {

private int mType;
private Object mParam;

InOutTypeWrapper(Object param, Class<?> mParamType) {
mType = Utils.getTypeByClass(mParamType);
mParam = param;
}

@Override
public int getType() {
return mType;
}

@Override
public Object getParam() {
return mParam;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Type type = TypeFactory.getType(mType);
type.writeToParcel(dest, flags, mParam);
}

@Override
public void readFromParcel(Parcel in) {
mType = in.readInt();
OutType type = (OutType) TypeFactory.getType(mType);
type.readFromParcel(in, mParam);
}

private InOutTypeWrapper(Parcel in) {
mType = in.readInt();
Type type = TypeFactory.getType(mType);
mParam = type.createFromParcel(in);
}

public static final Creator<InOutTypeWrapper> CREATOR = new Creator<InOutTypeWrapper>() {
@Override
public InOutTypeWrapper createFromParcel(Parcel source) {
return new InOutTypeWrapper(source);
}

@Override
public InOutTypeWrapper[] newArray(int size) {
return new InOutTypeWrapper[size];
}
};
}

+ 67
- 0
andlinker/src/main/java/com/codezjx/andlinker/InTypeWrapper.java Ver fichero

@@ -0,0 +1,67 @@
package com.codezjx.andlinker;

import android.os.Parcel;

/**
* Created by codezjx on 2017/11/19.<br/>
*/
final class InTypeWrapper implements BaseTypeWrapper {
private int mType;
private Object mParam;

InTypeWrapper(Object param, Class<?> mParamType) {
mType = Utils.getTypeByClass(mParamType);
mParam = param;
}

@Override
public int getType() {
return mType;
}

@Override
public Object getParam() {
return mParam;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
// Return if write return value, because in type won't readFromParcel
if (flags == PARCELABLE_WRITE_RETURN_VALUE) {
return;
}
dest.writeInt(mType);
Type type = TypeFactory.getType(mType);
type.writeToParcel(dest, flags, mParam);
}

@Override
public void readFromParcel(Parcel in) {
// Nothing to do with in type
}

private InTypeWrapper(Parcel in) {
mType = in.readInt();
Type type = TypeFactory.getType(mType);
mParam = type.createFromParcel(in);
}

public static final Creator<InTypeWrapper> CREATOR = new Creator<InTypeWrapper>() {
@Override
public InTypeWrapper createFromParcel(Parcel source) {
return new InTypeWrapper(source);
}

@Override
public InTypeWrapper[] newArray(int size) {
return new InTypeWrapper[size];
}
};
}

+ 197
- 0
andlinker/src/main/java/com/codezjx/andlinker/Invoker.java Ver fichero

@@ -0,0 +1,197 @@
package com.codezjx.andlinker;

import android.os.Binder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;

import com.codezjx.andlinker.annotation.RemoteInterface;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.ConcurrentHashMap;

/**
* Created by codezjx on 2017/10/3.<br/>
*/
final class Invoker {
private static final String TAG = "Invoker";

private final ConcurrentHashMap<String, Class<?>> mCallbackClassTypes;
private final ConcurrentHashMap<String, MethodExecutor> mMethodExecutors;
private final RemoteCallbackList<ICallback> mCallbackList;
Invoker() {
mCallbackClassTypes = new ConcurrentHashMap<String, Class<?>>();
mMethodExecutors = new ConcurrentHashMap<String, MethodExecutor>();
mCallbackList = new RemoteCallbackList<ICallback>();
}

private void handleCallbackClass(Class<?> clazz, boolean isRegister) {
if (!clazz.isAnnotationPresent(RemoteInterface.class)) {
throw new IllegalArgumentException("Callback interface doesn't has @RemoteInterface annotation.");
}
String className = clazz.getSimpleName();
if (isRegister) {
mCallbackClassTypes.putIfAbsent(className, clazz);
} else {
mCallbackClassTypes.remove(className);
}
}

private void handleObject(Object target, boolean isRegister) {
if (target == null) {
throw new NullPointerException("Object to (un)register must not be null.");
}
Class<?>[] interfaces = target.getClass().getInterfaces();
if (interfaces.length != 1) {
throw new IllegalArgumentException("Remote object must extend just one interface.");
}
Class<?> clazz = interfaces[0];
if (!clazz.isAnnotationPresent(RemoteInterface.class)) {
throw new IllegalArgumentException("Interface doesn't has @RemoteInterface annotation.");
}
// Cache all annotation method
String clsName = clazz.getSimpleName();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
// The compiler sometimes creates synthetic bridge methods as part of the
// type erasure process. As of JDK8 these methods now include the same
// annotations as the original declarations. They should be ignored for
// subscribe/produce.
if (method.isBridge()) {
continue;
}
String methodName = method.getName();
String key = createMethodExecutorKey(clsName, methodName);
if (isRegister) {
MethodExecutor executor = new MethodExecutor(target, method);
MethodExecutor preExecutor = mMethodExecutors.putIfAbsent(key, executor);
if (preExecutor != null) {
throw new IllegalStateException("Key conflict with class:" + clsName + " method:" + methodName
+ ". Please try another class/method name.");
}
} else {
mMethodExecutors.remove(key);
}
// Cache callback class if exist
Class<?>[] paramCls = method.getParameterTypes();
Annotation[][] paramAnnotations = method.getParameterAnnotations();
for (int i = 0; i < paramCls.length; i++) {
Class<?> cls = paramCls[i];
Annotation[] annotations = paramAnnotations[i];
if (!containCallbackAnnotation(annotations)) {
continue;
}
handleCallbackClass(cls, isRegister);
}
}
}

private boolean containCallbackAnnotation(Annotation[] annotations) {
if (annotations == null) {
return false;
}
for (Annotation annotation : annotations) {
if (annotation instanceof com.codezjx.andlinker.annotation.Callback) {
return true;
}
}
return false;
}

void registerObject(Object target) {
handleObject(target, true);
}

void unRegisterObject(Object target) {
handleObject(target, false);
}

Response invoke(Request request) {
BaseTypeWrapper[] wrappers = request.getArgsWrapper();
Object[] args = new Object[wrappers.length];
for (int i = 0; i < wrappers.length; i++) {
// Assign the origin args parameter
args[i] = wrappers[i].getParam();
if (wrappers[i].getType() == BaseTypeWrapper.TYPE_CALLBACK) {
int pid = Binder.getCallingPid();
String clazzName = ((CallbackTypeWrapper) wrappers[i]).getClassName();
Class<?> clazz = getCallbackClass(clazzName);
if (clazz == null) {
throw new IllegalStateException("Can't find callback class: " + clazzName);
}
args[i] = getCallbackProxy(clazz, pid);
}
}
MethodExecutor executor = getMethodExecutor(request);
if (executor == null) {
String errMsg = String.format("The method '%s' you call was not exist!", request.getMethodName());
return new Response(Response.STATUS_CODE_NOT_FOUND, errMsg, null);
}
return executor.execute(args);
}

RemoteCallbackList<ICallback> getCallbackList() {
return mCallbackList;
}

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
private <T> T getCallbackProxy(final Class<T> service, final int pid) {
Utils.validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
final int len = mCallbackList.beginBroadcast();
for (int i = 0; i < len; i++) {
int cookiePid = (int) mCallbackList.getBroadcastCookie(i);
if (cookiePid == pid) {
try {
Request request = createCallbackRequest(service.getSimpleName(), method.getName(), args);
Response response = mCallbackList.getBroadcastItem(i).callback(request);
result = response.getResult();
if (response.getStatusCode() != Response.STATUS_CODE_SUCCESS) {
Logger.e(TAG, "Execute remote callback fail: " + response.toString());
}
} catch (RemoteException e) {
Logger.e(TAG, "Error when execute callback!", e);
}
break;
}
}
mCallbackList.finishBroadcast();
return result;
}
});
}

private Request createCallbackRequest(String targetClass, String methodName, Object[] args) {
BaseTypeWrapper[] wrappers = new BaseTypeWrapper[args.length];
for (int i = 0; i < args.length; i++) {
wrappers[i] = new InTypeWrapper(args[i], args[i].getClass());
}
return new Request(targetClass, methodName, wrappers);
}

private Class<?> getCallbackClass(String className) {
return mCallbackClassTypes.get(className);
}

private String createMethodExecutorKey(String clsName, String methodName) {
StringBuilder sb = new StringBuilder();
sb.append(clsName)
.append('-')
.append(methodName);
return sb.toString();
}

private MethodExecutor getMethodExecutor(Request request) {
String key = createMethodExecutorKey(request.getTargetClass(), request.getMethodName());
return mMethodExecutors.get(key);
}
}

+ 58
- 0
andlinker/src/main/java/com/codezjx/andlinker/LinkerBinderImpl.java Ver fichero

@@ -0,0 +1,58 @@
package com.codezjx.andlinker;

import android.os.Binder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;

/**
* Created by codezjx on 2017/9/13.<br/>
*/
final class LinkerBinderImpl extends ITransfer.Stub implements AndLinkerBinder {
private static final String TAG = "LinkerBinder";
private RemoteCallbackList<ICallback> mCallbackList;
private Invoker mInvoker;

LinkerBinderImpl() {
mInvoker = new Invoker();
mCallbackList = mInvoker.getCallbackList();
}

@Override
public void registerObject(Object target) {
mInvoker.registerObject(target);
}

@Override
public void unRegisterObject(Object target) {
mInvoker.unRegisterObject(target);
}
@Override
public Response execute(Request request) throws RemoteException {
for (BaseTypeWrapper wrapper : request.getArgsWrapper()) {
Logger.d(TAG, "Receive param, value:" + wrapper.getParam()
+ " type:" + (wrapper.getParam() != null ? wrapper.getParam().getClass() : "null"));
}
Logger.d(TAG, "Receive request:" + request.getMethodName());
return mInvoker.invoke(request);
}

@Override
public void register(ICallback callback) throws RemoteException {
int pid = Binder.getCallingPid();
Logger.d(TAG, "register callback:" + callback + " pid:" + pid);
if (callback != null) {
mCallbackList.register(callback, pid);
}
}

@Override
public void unRegister(ICallback callback) throws RemoteException {
int pid = Binder.getCallingPid();
Logger.d(TAG, "unRegister callback:" + callback + " pid:" + pid);
if (callback != null) {
mCallbackList.unregister(callback);
}
}
}

+ 127
- 0
andlinker/src/main/java/com/codezjx/andlinker/Logger.java Ver fichero

@@ -0,0 +1,127 @@
package com.codezjx.andlinker;

import android.os.Build;
import android.util.Log;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Created by codezjx on 2018/1/23.<br/>
*/
final class Logger {

private Logger() {
// private constructor
}

private static final String DEFAULT_LOG_TAG = "Logger";
private static final int MAX_TAG_LENGTH = 23;
// 3 method calls inside Logger
private static final int CALL_STACK_INDEX = 3;
private static final Pattern ANONYMOUS_CLASS = Pattern.compile("(\\$\\d+)+$");
static boolean sEnable = false;

static void v(String msg) {
log(Log.VERBOSE, null, msg, null);
}

static void v(String tag, String msg) {
log(Log.VERBOSE, tag, msg, null);
}

static void d(String msg) {
log(Log.DEBUG, null, msg, null);
}
static void d(String tag, String msg) {
log(Log.DEBUG, tag, msg, null);
}

static void i(String msg) {
log(Log.INFO, null, msg, null);
}

static void i(String tag, String msg) {
log(Log.INFO, tag, msg, null);
}

static void w(String msg) {
log(Log.WARN, null, msg, null);
}

static void w(String tag, String msg) {
log(Log.WARN, tag, msg, null);
}

static void w(String msg, Throwable t) {
log(Log.WARN, null, msg, t);
}

static void w(String tag, String msg, Throwable t) {
log(Log.WARN, tag, msg, t);
}

static void e(String msg) {
log(Log.ERROR, null, msg, null);
}

static void e(String tag, String msg) {
log(Log.ERROR, tag, msg, null);
}

static void e(String msg, Throwable t) {
log(Log.ERROR, null, msg, t);
}

static void e(String tag, String msg, Throwable t) {
log(Log.ERROR, tag, msg, t);
}

private static void log(int priority, String tag, String msg, Throwable t) {
if (!sEnable) {
return;
}
String curTag = (tag != null && tag.trim().length() > 0) ? tag : getTag();
String curMsg = (t != null) ? (msg + '\n' + getStackTraceString(t)) : msg;
Log.println(priority, curTag, curMsg);
}
private static String getStackTraceString(Throwable t) {
if (t == null) {
return "";
}
// Don't replace this with Log.getStackTraceString() - it hides
// UnknownHostException, which is not what we want.
StringWriter sw = new StringWriter(256);
PrintWriter pw = new PrintWriter(sw, false);
t.printStackTrace(pw);
pw.flush();
return sw.toString();
}

private static String getTag() {
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
if (stackTrace.length <= CALL_STACK_INDEX) {
Log.e(DEFAULT_LOG_TAG, "Synthetic stacktrace didn't have enough elements, use the default logger tag, are you using proguard?");
return DEFAULT_LOG_TAG;
}
return createStackElementTag(stackTrace[CALL_STACK_INDEX]);
}

private static String createStackElementTag(StackTraceElement element) {
String tag = element.getClassName();
Matcher m = ANONYMOUS_CLASS.matcher(tag);
if (m.find()) {
tag = m.replaceAll("");
}
tag = tag.substring(tag.lastIndexOf('.') + 1);
// Tag length limit was removed in API 24.
if (tag.length() <= MAX_TAG_LENGTH || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return tag;
}
return tag.substring(0, MAX_TAG_LENGTH);
}
}

+ 50
- 0
andlinker/src/main/java/com/codezjx/andlinker/MethodExecutor.java Ver fichero

@@ -0,0 +1,50 @@
package com.codezjx.andlinker;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* Created by codezjx on 2017/10/22.<br/>
*/
final class MethodExecutor {
/** Target object to invoke. */
private final Object mTarget;
/** Method to execute. */
private final Method mMethod;

MethodExecutor(Object target, Method method) {
if (target == null) {
throw new NullPointerException("Target cannot be null.");
}
if (method == null) {
throw new NullPointerException("Method cannot be null.");
}

mTarget = target;
mMethod = method;
method.setAccessible(true);
}

Response execute(Object[] args) {
Object result = null;
int statusCode = Response.STATUS_CODE_SUCCESS;
String resultMsg = String.format("Call method '%s' successfully!", mMethod.getName());
Throwable throwable = null;
try {
result = mMethod.invoke(mTarget, args);
} catch (IllegalAccessException e) {
statusCode = Response.STATUS_CODE_ILLEGAL_ACCESS;
throwable = e;
} catch (InvocationTargetException e) {
statusCode = Response.STATUS_CODE_INVOCATION_FAIL;
throwable = e;
}
if (throwable != null) {
resultMsg = "Exception occur when execute method:" + mMethod.getName() + '\n' + throwable.getMessage();
}
return new Response(statusCode, resultMsg, result);
}
}

+ 109
- 0
andlinker/src/main/java/com/codezjx/andlinker/OutType.java Ver fichero

@@ -0,0 +1,109 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.os.Parcelable;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
* Created by codezjx on 2017/11/30.<br/>
*/
interface OutType<T> extends Type<T> {

void readFromParcel(Parcel in, T val);

final class ParcelableType implements OutType<Parcelable> {
private static final String TAG = "ParcelableType";

@Override
public void writeToParcel(Parcel dest, int flags, Parcelable val) {
if (flags == Parcelable.PARCELABLE_WRITE_RETURN_VALUE) {
val.writeToParcel(dest, flags);
} else {
dest.writeParcelable(val, flags);
}
}

@Override
public Parcelable createFromParcel(Parcel in) {
return in.readParcelable(getClass().getClassLoader());
}

@Override
public void readFromParcel(Parcel in, Parcelable val) {
if (val instanceof SuperParcelable) {
((SuperParcelable) val).readFromParcel(in);
return;
}
Method method = Utils.getMethodReadFromParcel(val.getClass());
if (method == null) {
throw new IllegalArgumentException("Parcelable parameter with @Out or @Inout annotation must " +
"declare the public readFromParcel() method or implements interface SuperParcelable. " +
"Error parameter type: " + val.getClass().getName());
}
try {
method.invoke(val, in);
} catch (IllegalAccessException e) {
Logger.e(TAG, "Can't access method readFromParcel().", e);
} catch (InvocationTargetException e) {
Logger.e(TAG, "Method readFromParcel() throws an exception.", e);
}
}
}

final class ListType implements OutType<List> {

@Override
public void writeToParcel(Parcel dest, int flags, List val) {
dest.writeList(val);
}

@Override
public List createFromParcel(Parcel in) {
return in.readArrayList(getClass().getClassLoader());
}

@Override
public void readFromParcel(Parcel in, List val) {
// Clear the list before read list
val.clear();
int N = in.readInt();
while (N > 0) {
Object value = in.readValue(getClass().getClassLoader());
val.add(value);
N--;
}
}
}

final class MapType implements OutType<Map> {

@Override
public void writeToParcel(Parcel dest, int flags, Map val) {
dest.writeMap(val);
}

@Override
public Map createFromParcel(Parcel in) {
return in.readHashMap(getClass().getClassLoader());
}

@Override
public void readFromParcel(Parcel in, Map val) {
ClassLoader loader = getClass().getClassLoader();
// Clear the map before read map
val.clear();
int N = in.readInt();
while (N > 0) {
Object key = in.readValue(loader);
Object value = in.readValue(loader);
val.put(key, value);
N--;
}
}
}
}

+ 95
- 0
andlinker/src/main/java/com/codezjx/andlinker/OutTypeWrapper.java Ver fichero

@@ -0,0 +1,95 @@
package com.codezjx.andlinker;

import android.os.Parcel;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;

/**
* Created by codezjx on 2017/11/30.<br/>
*/
final class OutTypeWrapper implements BaseTypeWrapper {

private int mType;
private Object mParam;

OutTypeWrapper(Object param, Class<?> mParamType) {
mType = Utils.getTypeByClass(mParamType);
mParam = param;
}

@Override
public int getType() {
return mType;
}

@Override
public Object getParam() {
return mParam;
}


@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Type type = TypeFactory.getType(mType);
if (flags == PARCELABLE_WRITE_RETURN_VALUE) {
type.writeToParcel(dest, flags, mParam);
} else {
if (mType == BaseTypeWrapper.TYPE_PARCELABLE) {
dest.writeString(mParam.getClass().getName());
} else if (mType == BaseTypeWrapper.TYPE_PARCELABLEARRAY) {
dest.writeInt(Array.getLength(mParam));
dest.writeString(mParam.getClass().getComponentType().getName());
} else if (Utils.isArrayType(mType)) {
// array type just write length
dest.writeInt(Array.getLength(mParam));
}
}
}

@Override
public void readFromParcel(Parcel in) {
mType = in.readInt();
OutType type = (OutType) TypeFactory.getType(mType);
type.readFromParcel(in, mParam);
}

private OutTypeWrapper(Parcel in) {
mType = in.readInt();
if (mType == BaseTypeWrapper.TYPE_PARCELABLE) {
String clsName = in.readString();
mParam = Utils.createObjFromClassName(clsName);
} else if (mType == BaseTypeWrapper.TYPE_PARCELABLEARRAY) {
int length = in.readInt();
String componentType = in.readString();
mParam = Utils.createArrayFromComponentType(componentType, length);
} else if (mType == BaseTypeWrapper.TYPE_LIST) {
mParam = new ArrayList();
} else if (mType == BaseTypeWrapper.TYPE_MAP) {
mParam = new HashMap();
} else if (Utils.isArrayType(mType)) {
int length = in.readInt();
ArrayType type = (ArrayType) TypeFactory.getType(mType);
mParam = type.newInstance(length);
}
}

public static final Creator<OutTypeWrapper> CREATOR = new Creator<OutTypeWrapper>() {
@Override
public OutTypeWrapper createFromParcel(Parcel source) {
return new OutTypeWrapper(source);
}

@Override
public OutTypeWrapper[] newArray(int size) {
return new OutTypeWrapper[size];
}
};
}

+ 80
- 0
andlinker/src/main/java/com/codezjx/andlinker/ParameterHandler.java Ver fichero

@@ -0,0 +1,80 @@
package com.codezjx.andlinker;

import com.codezjx.andlinker.annotation.In;
import com.codezjx.andlinker.annotation.Inout;
import com.codezjx.andlinker.annotation.Out;

import java.lang.annotation.Annotation;

/**
* Created by codezjx on 2017/9/17.<br/>
*/
interface ParameterHandler<T> {

void apply(RequestBuilder builder, T value, int index);
final class CallbackHandler<T> implements ParameterHandler<T> {

Class<?> mParamType;

CallbackHandler(Class<?> paramType) {
mParamType = paramType;
}

@Override
public void apply(RequestBuilder builder, T value, int index) {
Logger.d("CallbackHandler", "ParameterHandler mParamType:" + mParamType + " value:" + value);
String className = mParamType.getSimpleName();
CallbackTypeWrapper wrapper = new CallbackTypeWrapper(className);
builder.applyWrapper(index, wrapper);
}

}
final class ParamDirectionHandler<T> implements ParameterHandler<T> {

Annotation mAnnotation;
Class<?> mParamType;

ParamDirectionHandler(Annotation annotation, Class<?> paramType) {
mAnnotation = annotation;
mParamType = paramType;
}

@Override
public void apply(RequestBuilder builder, T value, int index) {
Logger.d("ParamDirectionHandler", " mParamType:" + mParamType + " value:" + value + " index:" + index);
if (Utils.canOnlyBeInType(mParamType) && !(mAnnotation instanceof In)) {
throw new IllegalArgumentException("Primitives are in by default, and cannot be otherwise.");
}
BaseTypeWrapper wrapper = null;
if (mAnnotation instanceof In) {
wrapper = new InTypeWrapper(value, mParamType);
} else if (mAnnotation instanceof Out) {
wrapper = new OutTypeWrapper(value, mParamType);
} else if (mAnnotation instanceof Inout) {
wrapper = new InOutTypeWrapper(value, mParamType);
}
builder.applyWrapper(index, wrapper);
}
}
final class DefaultParameterHandler<T> implements ParameterHandler<T> {

Class<?> mParamType;

DefaultParameterHandler(Class<?> paramType) {
mParamType = paramType;
}

@Override
public void apply(RequestBuilder builder, T value, int index) {
if (Utils.canOnlyBeInType(mParamType)) {
InTypeWrapper wrapper = new InTypeWrapper(value, mParamType);
builder.applyWrapper(index, wrapper);
} else {
throw new IllegalArgumentException("Parameter type '" + mParamType.getSimpleName() + "' can be an out type, so you must declare it as @In, @Out or @Inout.");
}
}
}
}

+ 131
- 0
andlinker/src/main/java/com/codezjx/andlinker/RemoteCall.java Ver fichero

@@ -0,0 +1,131 @@
package com.codezjx.andlinker;

import android.os.RemoteException;

import static com.codezjx.andlinker.Utils.checkNotNull;

/**
* Created by codezjx on 2017/10/14.<br/>
*/
final class RemoteCall implements Call<Object> {
private static final String TAG = "RemoteCall";

private final ITransfer mTransferService;
private final ServiceMethod mServiceMethod;
private final Object[] mArgs;
private final Dispatcher mDispatcher;
private volatile boolean mExecuted;
private volatile boolean mCanceled;

RemoteCall(ITransfer transferService, ServiceMethod serviceMethod, Object[] args, Dispatcher dispatcher) {
mTransferService = transferService;
mServiceMethod = serviceMethod;
mArgs = args;
mDispatcher = dispatcher;
}

private Object executeInternal() throws RemoteException {
if (mTransferService == null) {
Logger.e(TAG, "TransferService null when execute, this may occur if the client is not already bind to the service.");
return null;
}
@SuppressWarnings("unchecked")
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) mServiceMethod.getParameterHandlers();

int argumentCount = mArgs != null ? mArgs.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}

RequestBuilder requestBuilder = new RequestBuilder(mServiceMethod.getClassName(), mServiceMethod.getMethodName(), argumentCount, mServiceMethod.isOneWay());
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, mArgs[p], p);
}
Response response = mTransferService.execute(requestBuilder.build());
// May return null in one-way mode.
if (response == null) {
return null;
}
if (response.getStatusCode() != Response.STATUS_CODE_SUCCESS) {
Logger.e(TAG, "Execute remote call fail: " + response.toString());
}
return response.getResult();
}

@Override
public Object execute() {
checkExecuted();
if (mCanceled) {
Logger.w(TAG, "Already canceled");
return null;
}
Object result = null;
try {
result = executeInternal();
} catch (RemoteException e) {
e.printStackTrace();
}
return result;
}

@Override
public void enqueue(Callback<Object> callback) {
checkNotNull(callback, "callback == null");
checkExecuted();
if (mCanceled) {
Logger.w(TAG, "Already canceled");
return;
}
mDispatcher.enqueue(new AsyncCall(callback));
}

private void checkExecuted() {
synchronized (this) {
if (mExecuted) {
throw new IllegalStateException("Already executed.");
}
mExecuted = true;
}
}
final class AsyncCall implements Runnable {
private Callback<Object> mCallback;

AsyncCall(Callback<Object> callback) {
mCallback = callback;
}

@Override
public void run() {
try {
Object result = executeInternal();
mCallback.onResponse(RemoteCall.this, result);
} catch (RemoteException e) {
e.printStackTrace();
mCallback.onFailure(RemoteCall.this, e);
}
}
}

@Override
public synchronized boolean isExecuted() {
return mExecuted;
}

@Override
public void cancel() {
mCanceled = true;
}

@Override
public boolean isCanceled() {
return mCanceled;
}
}

+ 134
- 0
andlinker/src/main/java/com/codezjx/andlinker/Request.java Ver fichero

@@ -0,0 +1,134 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.os.Parcelable;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
* Created by codezjx on 2017/9/13.<br/>
*/
final class Request implements SuperParcelable {

private String mTargetClass;
private String mMethodName;
private BaseTypeWrapper[] mArgsWrapper;
// This field use for client slide only
private boolean mOneWay = false;

Request(String targetClass, String methodName, BaseTypeWrapper[] argsWrapper) {
this(targetClass, methodName, argsWrapper, false);
}

Request(String targetClass, String methodName, BaseTypeWrapper[] argsWrapper, boolean oneWay) {
mTargetClass = targetClass;
mMethodName = methodName;
mArgsWrapper = argsWrapper;
mOneWay = oneWay;
}
@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTargetClass);
dest.writeString(mMethodName);
if (flags == PARCELABLE_WRITE_RETURN_VALUE) {
writeParcelableArrayToParcel(dest, mArgsWrapper, flags);
} else {
dest.writeParcelableArray(mArgsWrapper, flags);
}
}

@Override
public void readFromParcel(Parcel in) {
mTargetClass = in.readString();
mMethodName = in.readString();
readParcelableArrayFromParcel(in, mArgsWrapper);
}

private Request(Parcel in) {
mTargetClass = in.readString();
mMethodName = in.readString();
mArgsWrapper = readParcelableArray(getClass().getClassLoader(), BaseTypeWrapper.class, in);
}

private <T extends BaseTypeWrapper> void writeParcelableArrayToParcel(Parcel dest, T[] value, int parcelableFlags) {
if (value != null) {
int N = value.length;
dest.writeInt(N);
for (int i = 0; i < N; i++) {
value[i].writeToParcel(dest, parcelableFlags);
}
} else {
dest.writeInt(-1);
}
}

private <T extends BaseTypeWrapper> void readParcelableArrayFromParcel(Parcel in, T[] value) {
int N = in.readInt();
if (N < 0) {
return;
}
for (int i = 0; i < N; i++) {
value[i].readFromParcel(in);
}
}

/**
* Code from {@link Parcel}.readParcelableArray(ClassLoader loader, Class<T> clazz), it's a hide method.
*/
@SuppressWarnings("unchecked")
private <T extends Parcelable> T[] readParcelableArray(ClassLoader loader, Class<T> clazz, Parcel in) {
int N = in.readInt();
if (N < 0) {
return null;
}
T[] p = (T[]) Array.newInstance(clazz, N);
for (int i = 0; i < N; i++) {
p[i] = in.readParcelable(loader);
}
return p;
}

public static final Creator<Request> CREATOR = new Creator<Request>() {
@Override
public Request createFromParcel(Parcel source) {
return new Request(source);
}

@Override
public Request[] newArray(int size) {
return new Request[size];
}
};

String getTargetClass() {
return mTargetClass;
}

String getMethodName() {
return mMethodName;
}

boolean isOneWay() {
return mOneWay;
}

BaseTypeWrapper[] getArgsWrapper() {
return mArgsWrapper;
}

@Override
public String toString() {
return "Request{" +
"mTargetClass='" + mTargetClass + '\'' +
", mMethodName='" + mMethodName + '\'' +
", mArgsWrapper=" + Arrays.toString(mArgsWrapper) +
'}';
}
}

+ 31
- 0
andlinker/src/main/java/com/codezjx/andlinker/RequestBuilder.java Ver fichero

@@ -0,0 +1,31 @@
package com.codezjx.andlinker;

/**
* Created by codezjx on 2017/11/5.<br/>
*/
final class RequestBuilder {

private String mTargetClass;
private String mMethodName;
private BaseTypeWrapper[] mParameterWrappers;
private boolean mOneWay;

RequestBuilder(String targetClass, String methodName, int argumentCount, boolean oneWay) {
mTargetClass = targetClass;
mMethodName = methodName;
mParameterWrappers = new BaseTypeWrapper[argumentCount];
mOneWay = oneWay;
}

void applyWrapper(int index, BaseTypeWrapper wrapper) {
if (index < 0 || index >= mParameterWrappers.length) {
throw new IllegalArgumentException("Index out of range.");
}
mParameterWrappers[index] = wrapper;
}

Request build() {
return new Request(mTargetClass, mMethodName, mParameterWrappers, mOneWay);
}

}

+ 80
- 0
andlinker/src/main/java/com/codezjx/andlinker/Response.java Ver fichero

@@ -0,0 +1,80 @@
package com.codezjx.andlinker;

import android.os.Parcel;

/**
* Created by codezjx on 2017/9/13.<br/>
*/
final class Response implements SuperParcelable {
static final int STATUS_CODE_SUCCESS = 200;
static final int STATUS_CODE_ILLEGAL_ACCESS = 400;
static final int STATUS_CODE_INVOCATION_FAIL = 401;
static final int STATUS_CODE_NOT_FOUND = 404;
private int mStatusCode;
private String mStatusMessage;
private Object mResult;

Response(int statusCode, String statusMessage, Object result) {
mStatusCode = statusCode;
mStatusMessage = statusMessage;
mResult = result;
}
@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mStatusCode);
dest.writeString(mStatusMessage);
dest.writeValue(mResult);
}

@Override
public void readFromParcel(Parcel in) {
mStatusCode = in.readInt();
mStatusMessage = in.readString();
mResult = in.readValue(getClass().getClassLoader());
}

private Response(Parcel in) {
readFromParcel(in);
}

public static final Creator<Response> CREATOR = new Creator<Response>() {
@Override
public Response createFromParcel(Parcel source) {
return new Response(source);
}

@Override
public Response[] newArray(int size) {
return new Response[size];
}
};

int getStatusCode() {
return mStatusCode;
}

String getStatusMessage() {
return mStatusMessage;
}

Object getResult() {
return mResult;
}

@Override
public String toString() {
return "Response{" +
"mStatusCode=" + mStatusCode +
", mStatusMessage='" + mStatusMessage + '\'' +
", mResult=" + mResult +
'}';
}
}

+ 159
- 0
andlinker/src/main/java/com/codezjx/andlinker/ServiceMethod.java Ver fichero

@@ -0,0 +1,159 @@
package com.codezjx.andlinker;

import com.codezjx.andlinker.annotation.Callback;
import com.codezjx.andlinker.annotation.In;
import com.codezjx.andlinker.annotation.Inout;
import com.codezjx.andlinker.annotation.OneWay;
import com.codezjx.andlinker.annotation.Out;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

/**
* Created by codezjx on 2017/9/14.<br/>
* Adapts an invocation of an interface method into an AIDL call.
*/
final class ServiceMethod {
private static final String TAG = "ServiceMethod";

private CallAdapter mCallAdapter;
private String mClassName;
private String mMethodName;
private boolean mOneWay;
private ParameterHandler<?>[] mParameterHandlers;

ServiceMethod(Builder builder) {
mCallAdapter = builder.mCallAdapter;
mClassName = builder.mClassName;
mMethodName = builder.mMethodName;
mOneWay = builder.mOneWay;
mParameterHandlers = builder.mParameterHandlers;
}

CallAdapter getCallAdapter() {
return mCallAdapter;
}

String getClassName() {
return mClassName;
}

String getMethodName() {
return mMethodName;
}

boolean isOneWay() {
return mOneWay;
}

ParameterHandler<?>[] getParameterHandlers() {
return mParameterHandlers;
}

static final class Builder {

private AndLinker mLinker;
private Method mMethod;
private Annotation[] mMethodAnnotations;
private Annotation[][] mParameterAnnotationsArray;
private Type[] mParameterTypes;

private CallAdapter mCallAdapter;
private String mClassName = "";
private String mMethodName = "";
private boolean mOneWay = false;
private ParameterHandler<?>[] mParameterHandlers;

Builder(AndLinker linker, Method method) {
mLinker = linker;
mMethod = method;
mMethodAnnotations = method.getAnnotations();
mParameterAnnotationsArray = method.getParameterAnnotations();
mParameterTypes = method.getGenericParameterTypes();
}
ServiceMethod build() {
mCallAdapter = createCallAdapter();
mClassName = mMethod.getDeclaringClass().getSimpleName();
mMethodName = mMethod.getName();

for (Annotation annotation : mMethodAnnotations) {
if (annotation instanceof OneWay) {
mOneWay = true;
break;
}
}

int parameterCount = mParameterAnnotationsArray.length;
mParameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = mParameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = mParameterAnnotationsArray[p];
mParameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod(this);
}

private CallAdapter createCallAdapter() {
Type returnType = mMethod.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
Annotation[] annotations = mMethod.getAnnotations();
try {
//noinspection unchecked
return mLinker.findCallAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}

private ParameterHandler<?> parseParameter(int p, Type parameterType, Annotation[] annotations) {
Class<?> rawParameterType = Utils.getRawType(parameterType);
if (annotations == null || annotations.length == 0) {
return new ParameterHandler.DefaultParameterHandler<>(rawParameterType);
}
for (Annotation annotation : annotations) {
if (annotation instanceof Callback) {
return new ParameterHandler.CallbackHandler<>(rawParameterType);
} else if (annotation instanceof In || annotation instanceof Out || annotation instanceof Inout) {
return new ParameterHandler.ParamDirectionHandler<>(annotation, rawParameterType);
}
}
throw parameterError(p, "No support annotation found.");
}

private RuntimeException methodError(String message, Object... args) {
return methodError(null, message, args);
}

private RuntimeException methodError(Throwable cause, String message, Object... args) {
message = String.format(message, args);
return new IllegalArgumentException(message
+ "\n for method "
+ mMethod.getDeclaringClass().getSimpleName()
+ "."
+ mMethod.getName(), cause);
}

private RuntimeException parameterError(
Throwable cause, int p, String message, Object... args) {
return methodError(cause, message + " (parameter #" + (p + 1) + ")", args);
}

private RuntimeException parameterError(int p, String message, Object... args) {
return methodError(message + " (parameter #" + (p + 1) + ")", args);
}

}
}

+ 17
- 0
andlinker/src/main/java/com/codezjx/andlinker/SuperParcelable.java Ver fichero

@@ -0,0 +1,17 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.os.Parcelable;

/**
* Parcelable parameter classes with @Out or @Inout annotation must inherit from this class.
*/
public interface SuperParcelable extends Parcelable {

/**
* Reads the parcel contents into this object, so we can restore it.
* @param in The parcel to overwrite this object from.
*/
void readFromParcel(Parcel in);
}

+ 166
- 0
andlinker/src/main/java/com/codezjx/andlinker/Type.java Ver fichero

@@ -0,0 +1,166 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.text.TextUtils;

/**
* Created by codezjx on 2017/11/28.<br/>
*/
interface Type<T> {

void writeToParcel(Parcel dest, int flags, T val);

T createFromParcel(Parcel in);
final class EmptyType implements Type<Object> {
@Override
public void writeToParcel(Parcel dest, int flags, Object val) {
// Nothing to do
}

@Override
public Object createFromParcel(Parcel in) {
return null;
}
}

final class ByteType implements Type<Byte> {

@Override
public void writeToParcel(Parcel dest, int flags, Byte val) {
dest.writeByte(val);
}

@Override
public Byte createFromParcel(Parcel in) {
return in.readByte();
}
}
final class ShortType implements Type<Short> {

@Override
public void writeToParcel(Parcel dest, int flags, Short val) {
dest.writeInt(val.intValue());
}

@Override
public Short createFromParcel(Parcel in) {
return (short) in.readInt();
}
}

final class IntType implements Type<Integer> {

@Override
public void writeToParcel(Parcel dest, int flags, Integer val) {
dest.writeInt(val);
}

@Override
public Integer createFromParcel(Parcel in) {
return in.readInt();
}
}
final class LongType implements Type<Long> {

@Override
public void writeToParcel(Parcel dest, int flags, Long val) {
dest.writeLong(val);
}

@Override
public Long createFromParcel(Parcel in) {
return in.readLong();
}
}
final class FloatType implements Type<Float> {

@Override
public void writeToParcel(Parcel dest, int flags, Float val) {
dest.writeFloat(val);
}

@Override
public Float createFromParcel(Parcel in) {
return in.readFloat();
}
}
final class DoubleType implements Type<Double> {
@Override
public void writeToParcel(Parcel dest, int flags, Double val) {
dest.writeDouble(val);
}

@Override
public Double createFromParcel(Parcel in) {
return in.readDouble();
}
}
final class BooleanType implements Type<Boolean> {

@Override
public void writeToParcel(Parcel dest, int flags, Boolean val) {
dest.writeInt(val ? 1 : 0);
}

@Override
public Boolean createFromParcel(Parcel in) {
return in.readInt() == 1;
}
}
final class CharType implements Type<Character> {

@Override
public void writeToParcel(Parcel dest, int flags, Character val) {
dest.writeInt(((int) val));
}

@Override
public Character createFromParcel(Parcel in) {
return (char) in.readInt();
}
}
final class StringType implements Type<String> {

@Override
public void writeToParcel(Parcel dest, int flags, String val) {
dest.writeString(val);
}

@Override
public String createFromParcel(Parcel in) {
return in.readString();
}
}
final class CharSequenceType implements Type<CharSequence> {

@Override
public void writeToParcel(Parcel dest, int flags, CharSequence val) {
writeCharSequence(dest, val);
}

@Override
public CharSequence createFromParcel(Parcel in) {
return readCharSequence(in);
}

static void writeCharSequence(Parcel dest, CharSequence val) {
TextUtils.writeToParcel(val, dest, 0);
}

static CharSequence readCharSequence(Parcel in) {
return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
}
}
}

+ 30
- 0
andlinker/src/main/java/com/codezjx/andlinker/TypeFactory.java Ver fichero

@@ -0,0 +1,30 @@
package com.codezjx.andlinker;

/**
* Created by codezjx on 2017/11/28.<br/>
*/
final class TypeFactory {

private TypeFactory() {
}

private static Type[] sTypeArr = {
new Type.EmptyType(),
new Type.ByteType(), new Type.ShortType(), new Type.IntType(), new Type.LongType(),
new Type.FloatType(), new Type.DoubleType(), new Type.BooleanType(), new Type.CharType(),
new ArrayType.ByteArrayType(), new ArrayType.ShortArrayType(), new ArrayType.IntArrayType(), new ArrayType.LongArrayType(),
new ArrayType.FloatArrayType(), new ArrayType.DoubleArrayType(), new ArrayType.BooleanArrayType(), new ArrayType.CharArrayType(),
new Type.StringType(), new ArrayType.StringArrayType(), new Type.CharSequenceType(), new ArrayType.CharSequenceArrayType(),
new OutType.ParcelableType(), new ArrayType.ParcelableArrayType(), new OutType.ListType(), new OutType.MapType()
};

static Type getType(int type) {
return sTypeArr[type];
}

static Type getType(Class<?> classType) {
return sTypeArr[Utils.getTypeByClass(classType)];
}

}

+ 227
- 0
andlinker/src/main/java/com/codezjx/andlinker/Utils.java Ver fichero

@@ -0,0 +1,227 @@
package com.codezjx.andlinker;

import android.os.Parcel;
import android.os.Parcelable;

import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.List;
import java.util.Map;

/**
* Created by codezjx on 2017/9/14.<br/>
*/
final class Utils {
private static final String TAG = "Utils";
private Utils() {
// private constructor
}

static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}

static boolean hasUnresolvableType(Type type) {
if (type instanceof Class<?>) {
return false;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
if (hasUnresolvableType(typeArgument)) {
return true;
}
}
return false;
}
if (type instanceof GenericArrayType) {
return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
}
if (type instanceof TypeVariable) {
return true;
}
if (type instanceof WildcardType) {
return true;
}
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + className);
}

static Class<?> getRawType(Type type) {
checkNotNull(type, "type == null");

if (type instanceof Class<?>) {
// Type is a normal class.
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;

// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
// suspects some pathological case related to nested classes exists.
Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
return (Class<?>) rawType;
}
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
if (type instanceof TypeVariable) {
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
return Object.class;
}
if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
}

throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
}

static <T> T checkNotNull(T object, String message) {
if (object == null) {
throw new NullPointerException(message);
}
return object;
}

static boolean canOnlyBeInType(Class<?> classType) {
return isPrimitiveType(classType) || classType == String.class || classType == CharSequence.class;
}

static boolean isArrayType(int type) {
return type == BaseTypeWrapper.TYPE_BYTEARRAY || type == BaseTypeWrapper.TYPE_SHORTARRAY || type == BaseTypeWrapper.TYPE_INTARRAY
|| type == BaseTypeWrapper.TYPE_LONGARRAY || type == BaseTypeWrapper.TYPE_FLOATARRAY || type == BaseTypeWrapper.TYPE_DOUBLEARRAY
|| type == BaseTypeWrapper.TYPE_BOOLEANARRAY || type == BaseTypeWrapper.TYPE_CHARARRAY || type == BaseTypeWrapper.TYPE_STRINGARRAY
|| type == BaseTypeWrapper.TYPE_CHARSEQUENCEARRAY || type == BaseTypeWrapper.TYPE_PARCELABLEARRAY;
}

static boolean isPrimitiveType(Class<?> classType) {
return classType.isPrimitive() || classType == Byte.class || classType == Short.class
|| classType == Integer.class || classType == Long.class || classType == Float.class
|| classType == Double.class || classType == Boolean.class || classType == Character.class;
}

static boolean isArrayType(Class<?> classType) {
return classType == byte[].class || classType == short[].class || classType == int[].class || classType == long[].class
|| classType == float[].class || classType == double[].class || classType == boolean[].class || classType == char[].class
|| classType == String[].class || classType == CharSequence[].class || classType == Parcelable[].class;
}

static int getTypeByClass(Class<?> classType) {
int type;
if (classType == byte.class || classType == Byte.class) {
type = BaseTypeWrapper.TYPE_BYTE;
} else if (classType == short.class || classType == Short.class) {
type = BaseTypeWrapper.TYPE_SHORT;
} else if (classType == int.class || classType == Integer.class) {
type = BaseTypeWrapper.TYPE_INT;
} else if (classType == long.class || classType == Long.class) {
type = BaseTypeWrapper.TYPE_LONG;
} else if (classType == float.class || classType == Float.class) {
type = BaseTypeWrapper.TYPE_FLOAT;
} else if (classType == double.class || classType == Double.class) {
type = BaseTypeWrapper.TYPE_DOUBLE;
} else if (classType == boolean.class || classType == Boolean.class) {
type = BaseTypeWrapper.TYPE_BOOLEAN;
} else if (classType == char.class || classType == Character.class) {
type = BaseTypeWrapper.TYPE_CHAR;
} else if (classType == byte[].class) {
type = BaseTypeWrapper.TYPE_BYTEARRAY;
} else if (classType == short[].class) {
type = BaseTypeWrapper.TYPE_SHORTARRAY;
} else if (classType == int[].class) {
type = BaseTypeWrapper.TYPE_INTARRAY;
} else if (classType == long[].class) {
type = BaseTypeWrapper.TYPE_LONGARRAY;
} else if (classType == float[].class) {
type = BaseTypeWrapper.TYPE_FLOATARRAY;
} else if (classType == double[].class) {
type = BaseTypeWrapper.TYPE_DOUBLEARRAY;
} else if (classType == boolean[].class) {
type = BaseTypeWrapper.TYPE_BOOLEANARRAY;
} else if (classType == char[].class) {
type = BaseTypeWrapper.TYPE_CHARARRAY;
} else if (classType == String.class) {
type = BaseTypeWrapper.TYPE_STRING;
} else if (classType == String[].class) {
type = BaseTypeWrapper.TYPE_STRINGARRAY;
} else if (classType == CharSequence.class) {
type = BaseTypeWrapper.TYPE_CHARSEQUENCE;
} else if (classType == CharSequence[].class) {
type = BaseTypeWrapper.TYPE_CHARSEQUENCEARRAY;
} else if (Parcelable.class.isAssignableFrom(classType)) {
type = BaseTypeWrapper.TYPE_PARCELABLE;
} else if (Parcelable[].class.isAssignableFrom(classType)) {
type = BaseTypeWrapper.TYPE_PARCELABLEARRAY;
} else if (List.class.isAssignableFrom(classType)) {
type = BaseTypeWrapper.TYPE_LIST;
} else if (Map.class.isAssignableFrom(classType)) {
type = BaseTypeWrapper.TYPE_MAP;
} else {
type = BaseTypeWrapper.TYPE_EMPTY;
}
return type;
}

static Object createObjFromClassName(String clsName) {
Object obj = null;
try {
obj = Class.forName(clsName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return obj;
}

static Object createArrayFromComponentType(String componentType, int length) {
Object obj = null;
try {
Class clsType = Class.forName(componentType);
obj = Array.newInstance(clsType, length);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return obj;
}

static boolean isStringBlank(String str) {
return str == null || str.trim().length() == 0;
}

static Method getMethodReadFromParcel(Class<?> cls) {
checkNotNull(cls, "Class must not be null.");
Method method = null;
try {
method = cls.getMethod("readFromParcel", Parcel.class);
} catch (NoSuchMethodException e) {
Logger.e(TAG, "No public readFromParcel() method in class:" + cls.getName());
} catch (SecurityException e) {
Logger.e(TAG, "SecurityException when get readFromParcel() method in class:" + cls.getName());
}
return method;
}
}

+ 27
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/DefaultCallAdapterFactory.java Ver fichero

@@ -0,0 +1,27 @@
package com.codezjx.andlinker.adapter;

import com.codezjx.andlinker.Call;
import com.codezjx.andlinker.CallAdapter;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

/**
* Default {@linkplain CallAdapter.Factory call adapter} which adapt {@link Call} to the execute result.
*/
public class DefaultCallAdapterFactory extends CallAdapter.Factory {

public static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations) {
return new CallAdapter<Object, Object>() {
@Override
public Object adapt(Call<Object> call) {
// Return the result
return call.execute();
}
};
}
}

+ 125
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/OriginalCallAdapterFactory.java Ver fichero

@@ -0,0 +1,125 @@
package com.codezjx.andlinker.adapter;

import android.os.Handler;
import android.os.Looper;

import com.codezjx.andlinker.Call;
import com.codezjx.andlinker.CallAdapter;
import com.codezjx.andlinker.Callback;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.concurrent.Executor;

/**
* A {@linkplain CallAdapter.Factory call adapter} which uses the original {@link Call}, just return as is.
*/
public class OriginalCallAdapterFactory extends CallAdapter.Factory {

private Executor mCallbackExecutor;
private OriginalCallAdapterFactory(Executor callbackExecutor) {
mCallbackExecutor = callbackExecutor;
}

/**
* Create {@link OriginalCallAdapterFactory} with default Android main thread executor.
*/
public static OriginalCallAdapterFactory create() {
return new OriginalCallAdapterFactory(new MainThreadExecutor());
}

/**
* Create {@link OriginalCallAdapterFactory} with specify {@link Executor}
* @param callbackExecutor The executor on which {@link Callback} methods are invoked
* when returning {@link Call} from your service method.
*/
public static OriginalCallAdapterFactory create(Executor callbackExecutor) {
return new OriginalCallAdapterFactory(callbackExecutor);
}

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations) {
if (getRawType(returnType) != Call.class) {
return null;
}
return new CallAdapter<Object, Call<?>>() {
@Override public Call<Object> adapt(Call<Object> call) {
// Return executor wrapper call
return new ExecutorCallbackCall<>(mCallbackExecutor, call);
}
};
}
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor mCallbackExecutor;
final Call<T> mDelegate;

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
mCallbackExecutor = callbackExecutor;
mDelegate = delegate;
}

@Override
public T execute() {
return mDelegate.execute();
}

@Override
public void enqueue(final Callback<T> callback) {
if (callback == null) {
throw new NullPointerException("callback == null");
}
mDelegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, final T response) {
mCallbackExecutor.execute(new Runnable() {
@Override
public void run() {
if (mDelegate.isCanceled()) {
// Emulate behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IllegalStateException("Already canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override
public void onFailure(Call<T> call, final Throwable t) {
mCallbackExecutor.execute(new Runnable() {
@Override
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}

@Override
public boolean isExecuted() {
return mDelegate.isExecuted();
}

@Override
public void cancel() {
mDelegate.cancel();
}

@Override
public boolean isCanceled() {
return mDelegate.isCanceled();
}
}
private static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {
handler.post(r);
}
}
}

+ 163
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/CallArbiter.java Ver fichero

@@ -0,0 +1,163 @@
package com.codezjx.andlinker.adapter.rxjava;

import com.codezjx.andlinker.Call;

import java.util.concurrent.atomic.AtomicInteger;

import rx.Producer;
import rx.Subscriber;
import rx.Subscription;
import rx.exceptions.CompositeException;
import rx.exceptions.Exceptions;
import rx.exceptions.OnCompletedFailedException;
import rx.exceptions.OnErrorFailedException;
import rx.exceptions.OnErrorNotImplementedException;
import rx.plugins.RxJavaPlugins;

/**
* Created by codezjx on 2017/10/16.<br/>
*/
final class CallArbiter<T> extends AtomicInteger implements Subscription, Producer {
private static final int STATE_WAITING = 0;
private static final int STATE_REQUESTED = 1;
private static final int STATE_HAS_RESPONSE = 2;
private static final int STATE_TERMINATED = 3;

private final Call<T> mCall;
private final Subscriber<? super T> mSubscriber;

private volatile T mResponse;

CallArbiter(Call<T> call, Subscriber<? super T> subscriber) {
super(STATE_WAITING);

mCall = call;
mSubscriber = subscriber;
}

@Override
public void unsubscribe() {
mCall.cancel();
}

@Override
public boolean isUnsubscribed() {
return mCall.isCanceled();
}

@Override
public void request(long amount) {
if (amount == 0) {
return;
}
while (true) {
int state = get();
switch (state) {
case STATE_WAITING:
if (compareAndSet(STATE_WAITING, STATE_REQUESTED)) {
return;
}
break; // State transition failed. Try again.

case STATE_HAS_RESPONSE:
if (compareAndSet(STATE_HAS_RESPONSE, STATE_TERMINATED)) {
deliverResponse(mResponse);
return;
}
break; // State transition failed. Try again.

case STATE_REQUESTED:
case STATE_TERMINATED:
return; // Nothing to do.

default:
throw new IllegalStateException("Unknown state: " + state);
}
}
}

void emitResponse(T response) {
while (true) {
int state = get();
switch (state) {
case STATE_WAITING:
this.mResponse = response;
if (compareAndSet(STATE_WAITING, STATE_HAS_RESPONSE)) {
return;
}
break; // State transition failed. Try again.

case STATE_REQUESTED:
if (compareAndSet(STATE_REQUESTED, STATE_TERMINATED)) {
deliverResponse(response);
return;
}
break; // State transition failed. Try again.

case STATE_HAS_RESPONSE:
case STATE_TERMINATED:
throw new AssertionError();

default:
throw new IllegalStateException("Unknown state: " + state);
}
}
}

private void deliverResponse(T response) {
try {
if (!isUnsubscribed()) {
mSubscriber.onNext(response);
}
} catch (OnCompletedFailedException
| OnErrorFailedException
| OnErrorNotImplementedException e) {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
return;
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
try {
mSubscriber.onError(t);
} catch (OnCompletedFailedException
| OnErrorFailedException
| OnErrorNotImplementedException e) {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
CompositeException composite = new CompositeException(t, inner);
RxJavaPlugins.getInstance().getErrorHandler().handleError(composite);
}
return;
}
try {
if (!isUnsubscribed()) {
mSubscriber.onCompleted();
}
} catch (OnCompletedFailedException
| OnErrorFailedException
| OnErrorNotImplementedException e) {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
RxJavaPlugins.getInstance().getErrorHandler().handleError(t);
}
}

void emitError(Throwable t) {
set(STATE_TERMINATED);

if (!isUnsubscribed()) {
try {
mSubscriber.onError(t);
} catch (OnCompletedFailedException
| OnErrorFailedException
| OnErrorNotImplementedException e) {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
CompositeException composite = new CompositeException(t, inner);
RxJavaPlugins.getInstance().getErrorHandler().handleError(composite);
}
}
}
}

+ 36
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/CallExecuteOnSubscribe.java Ver fichero

@@ -0,0 +1,36 @@
package com.codezjx.andlinker.adapter.rxjava;

import com.codezjx.andlinker.Call;

import rx.Observable.OnSubscribe;
import rx.Subscriber;
import rx.exceptions.Exceptions;

/**
* Created by codezjx on 2017/10/16.<br/>
*/
final class CallExecuteOnSubscribe<T> implements OnSubscribe<T> {

private final Call<T> mCall;

CallExecuteOnSubscribe(Call<T> call) {
mCall = call;
}

@Override
public void call(Subscriber<? super T> subscriber) {
CallArbiter<T> arbiter = new CallArbiter<>(mCall, subscriber);
subscriber.add(arbiter);
subscriber.setProducer(arbiter);

T response;
try {
response = mCall.execute();
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
arbiter.emitError(t);
return;
}
arbiter.emitResponse(response);
}
}

+ 35
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/RxJavaCallAdapter.java Ver fichero

@@ -0,0 +1,35 @@
package com.codezjx.andlinker.adapter.rxjava;

import com.codezjx.andlinker.Call;
import com.codezjx.andlinker.CallAdapter;

import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Scheduler;


/**
* Created by codezjx on 2017/10/16.<br/>
*/
final class RxJavaCallAdapter<R> implements CallAdapter<R, Observable<R>> {
private final Scheduler mScheduler;

RxJavaCallAdapter(Scheduler scheduler) {
mScheduler = scheduler;
}

@Override
public Observable<R> adapt(Call<R> call) {
OnSubscribe<R> subscribe = new CallExecuteOnSubscribe<>(call);
Observable<R> observable = Observable.create(subscribe);
if (mScheduler != null) {
observable = observable.subscribeOn(mScheduler);
}

return observable;
}


}

+ 47
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava/RxJavaCallAdapterFactory.java Ver fichero

@@ -0,0 +1,47 @@
package com.codezjx.andlinker.adapter.rxjava;

import com.codezjx.andlinker.CallAdapter;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import rx.Observable;
import rx.Scheduler;


/**
* A {@linkplain CallAdapter.Factory call adapter} which uses RxJava for creating observables.
*/
public class RxJavaCallAdapterFactory extends CallAdapter.Factory {

private final Scheduler mScheduler;

private RxJavaCallAdapterFactory(Scheduler scheduler) {
mScheduler = scheduler;
}

public static RxJavaCallAdapterFactory create() {
return new RxJavaCallAdapterFactory(null);
}

public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJavaCallAdapterFactory(scheduler);
}
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations) {
Class<?> rawType = getRawType(returnType);
if (rawType != Observable.class) {
return null;
}

if (!(returnType instanceof ParameterizedType)) {
throw new IllegalStateException("Observable return type must be parameterized"
+ " as Observable<Foo> or Observable<? extends Foo>");
}
return new RxJavaCallAdapter(mScheduler);
}
}

+ 66
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/CallExecuteObservable.java Ver fichero

@@ -0,0 +1,66 @@
package com.codezjx.andlinker.adapter.rxjava2;

import com.codezjx.andlinker.Call;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.CompositeException;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.plugins.RxJavaPlugins;

/**
* Created by codezjx on 2017/10/14.<br/>
*/
final class CallExecuteObservable<T> extends Observable<T> {

private final Call<T> mCall;

CallExecuteObservable(Call<T> call) {
mCall = call;
}

@Override
protected void subscribeActual(Observer<? super T> observer) {
observer.onSubscribe(new CallDisposable(mCall));
boolean terminated = false;
try {
T response = mCall.execute();
if (!mCall.isCanceled()) {
observer.onNext(response);
}
if (!mCall.isCanceled()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!mCall.isCanceled()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}

private static final class CallDisposable implements Disposable {
private final Call<?> mCall;

CallDisposable(Call<?> call) {
this.mCall = call;
}

@Override public void dispose() {
mCall.cancel();
}

@Override public boolean isDisposed() {
return mCall.isCanceled();
}
}
}

+ 38
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/RxJava2CallAdapter.java Ver fichero

@@ -0,0 +1,38 @@
package com.codezjx.andlinker.adapter.rxjava2;

import com.codezjx.andlinker.Call;
import com.codezjx.andlinker.CallAdapter;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Observable;
import io.reactivex.Scheduler;

/**
* Created by codezjx on 2017/10/14.<br/>
*/
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {

private final Scheduler mScheduler;
private final boolean mIsFlowable;

RxJava2CallAdapter(Scheduler scheduler, boolean isFlowable) {
mScheduler = scheduler;
mIsFlowable = isFlowable;
}

@Override
public Object adapt(Call<R> call) {
Observable<R> observable = new CallExecuteObservable<>(call);

if (mScheduler != null) {
observable = observable.subscribeOn(mScheduler);
}

if (mIsFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
return observable;
}

}

+ 50
- 0
andlinker/src/main/java/com/codezjx/andlinker/adapter/rxjava2/RxJava2CallAdapterFactory.java Ver fichero

@@ -0,0 +1,50 @@
package com.codezjx.andlinker.adapter.rxjava2;

import com.codezjx.andlinker.CallAdapter;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;

/**
* A {@linkplain CallAdapter.Factory call adapter} which uses RxJava 2 for creating observables.
*/
public class RxJava2CallAdapterFactory extends CallAdapter.Factory {

private final Scheduler mScheduler;

private RxJava2CallAdapterFactory(Scheduler scheduler) {
mScheduler = scheduler;
}

public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null);
}

public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler);
}

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations) {
Class<?> rawType = getRawType(returnType);
boolean isFlowable = (rawType == Flowable.class);
if (rawType != Observable.class && !isFlowable) {
return null;
}

if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
return new RxJava2CallAdapter(mScheduler, isFlowable);
}
}

+ 16
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/Callback.java Ver fichero

@@ -0,0 +1,16 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Indicate a parameter is a remote callback type.
*/
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Callback {

}

+ 16
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/In.java Ver fichero

@@ -0,0 +1,16 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Directional tag indicating which way the data goes, same as "in" tag in AIDL.
*/
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface In {
}

+ 16
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/Inout.java Ver fichero

@@ -0,0 +1,16 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Directional tag indicating which way the data goes, same as "inout" tag in AIDL.
*/
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Inout {
}

+ 17
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/OneWay.java Ver fichero

@@ -0,0 +1,17 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Indicate a remote call does not block, it simply sends the transaction data and immediately
* returns, same as "oneway" tag in AIDL.
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface OneWay {
}

+ 16
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/Out.java Ver fichero

@@ -0,0 +1,16 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Directional tag indicating which way the data goes, same as "out" tag in AIDL.
*/
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Out {
}

+ 16
- 0
andlinker/src/main/java/com/codezjx/andlinker/annotation/RemoteInterface.java Ver fichero

@@ -0,0 +1,16 @@
package com.codezjx.andlinker.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Specify the interface as remote service interface.
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface RemoteInterface {
}

+ 1
- 0
app/.gitignore Ver fichero

@@ -0,0 +1 @@
/build

+ 80
- 0
app/build.gradle Ver fichero

@@ -0,0 +1,80 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 26
buildToolsVersion '26.0.2'


defaultConfig {
applicationId "com.neusoft.possale"
minSdkVersion 21
targetSdkVersion 23
versionCode 7
versionName "20201123163124"
// jackOptions.enabled = true
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath = true
}
}
}

// compileOptions{
// sourceCompatibility org.gradle.api.JavaVersion.VERSION_1_8
// targetCompatibility org.gradle.api.JavaVersion.VERSION_1_8
// }
packagingOptions {
exclude 'META-INF/rxjava.properties'
// ... and any other excludes go here
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

// debug {
// applicationIdSuffix "debug"
// }
}
sourceSets { main { assets.srcDirs = ['src/main/assets', 'src/main/assets/'] } }
sourceSets {
main {
aidl.srcDirs = ['src/main/aidl/']
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:design:23.4.0'
//rxlifecycle
compile 'com.trello:rxlifecycle-components:1.0'
//rx
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.3.0'
//net
compile 'com.squareup.retrofit2:retrofit:2.4.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
compile 'com.squareup.retrofit2:converter-gson:2.4.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.10.0'
compile 'com.google.code.gson:gson:2.7'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile project(path: ':cardreader')
compile project(path: ':barcodescaner')
compile files('libs/butterknife-7.0.1.jar')
compile project(path: ':lib')
compile 'com.ttsea.jrxbus2:jrxbus2:1.0.3'
compile project(path: ':extendMediaPlay')
provided files('libs_ext/androidsim.jar')
implementation 'com.codezjx.library:andlinker:0.7.1'
}

BIN
app/libs/WTAndroidJar.jar Ver fichero


BIN
app/libs/armeabi/libjni.so Ver fichero


BIN
app/libs/armeabi/libusb.so Ver fichero


BIN
app/libs/butterknife-7.0.1.jar Ver fichero


BIN
app/libs/eventbus-3.0.0.jar Ver fichero


BIN
app/libs/litepal-1.3.0-src.jar Ver fichero


BIN
app/libs/printer.jar Ver fichero


BIN
app/libs/printer_library.jar Ver fichero


BIN
app/libs/rtdriver.jar Ver fichero


BIN
app/libs/screenlib.jar Ver fichero


BIN
app/libs_ext/androidsim.jar Ver fichero


+ 17
- 0
app/proguard-rules.pro Ver fichero

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\angel\Cmread_android_studio_sdk\android-sdk-windows/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

+ 13
- 0
app/src/androidTest/java/com/neusoft/possale/ApplicationTest.java Ver fichero

@@ -0,0 +1,13 @@
package com.neusoft.possale;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

+ 266
- 0
app/src/main/AndroidManifest.xml Ver fichero

@@ -0,0 +1,266 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.neusoft.possale">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.KOOLCLOUD_CONTACTLESS_CARD" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.KOOLCLOUD_PRINTER" />
<uses-permission android:name="com.hidglobal.ia.omnikey.service.permission.SMARTCARDIO" />
<!-- 外置存储存取权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.screen.portrait" />
<!-- 接收开机广播 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<!-- 交易权限 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.advance.special" />
<!-- 收银 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.multiPurchase" />
<!-- 余额查询 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.inquery" />
<!-- 积分查询 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.integralQuery" />
<!-- 当日撤销 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.posVoid" />
<!-- 隔日退货 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.refund" />
<!-- 积分退货 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.integralRefund" />
<!-- 二维码退货 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.qrRefund" />
<!-- 预授权 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.preauth" />
<!-- 追加预授权 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.addPreauth" />
<!-- 预授权确认 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.preauthEnd" />
<!-- 预授权撤销 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.preauthVoid" />
<!-- 查本机交易记录 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.queryTransRec" />
<!-- 获取终端信息 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.terminalInfo" />
<!-- 重打印交易凭条 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.trans.reprint" />
<!-- 设备使用权限 -->
<!-- 打印机 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.device.printer" />
<!-- 扫码器 -->
<uses-permission android:name="com.icbc.smartpos.bankpay.device.scanner" />

<uses-sdk android:targetSdkVersion="23" />

<application
android:name=".aplication.MyApplication"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:largeHeap="true"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".LoginActivity"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- 关机广播 -->
<receiver android:name=".service.recevier.ShutDownRecevier">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />

<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>

<!-- 开机广播 -->
<receiver android:name=".service.recevier.BootRecevier">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />

<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>

<receiver android:name=".service.recevier.UsbDeviceReceiver">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</receiver>

<activity
android:name=".home.MainActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape" />
<activity
android:name=".home.MainActivityA90"
android:launchMode="singleTask"
android:screenOrientation="portrait" />
<activity
android:name=".cashfunction.activity.CashFunctionActivity"
android:launchMode="singleTask" />
<activity
android:name=".cashfunction.activity.CashMemberLoginActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:theme="@style/CustomActivityDialogStyle" />
<activity
android:name=".cashfunction.activity.PayOrderActivity"
android:launchMode="singleTask"
android:theme="@style/CustomActivityDialogStyle" />
<activity
android:name=".cashfunction.activity.CountInputActivity"
android:launchMode="singleTask"
android:theme="@style/CustomActivityDialogStyle" />
<activity
android:name=".cashfunction.activity.MemberPayActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:theme="@style/CustomActivityDialogStyle"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".set.activity.SettingActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape" />
<activity
android:name=".set.activity.SettingActivityA90"
android:launchMode="singleTask"
android:screenOrientation="portrait" />
<activity
android:name=".set.activity.ShoppingCartModeActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"/>
<activity
android:name=".paymanage.activity.TradeManageActivity"
android:launchMode="singleTask" />
<activity
android:name=".shop.activity.SelectShopActivity"
android:launchMode="singleTask"/>
<activity
android:name=".member.activity.MemberLoginActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberLoginSuccessActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberRechargeActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberRechargeChangeDetailsActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberRegisterActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberIntegralConsumeActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:theme="@style/CustomActivityDialogStyle"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.MemberMenuActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.CardActivateActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.CardRechargeActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.CardRefundActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".member.activity.CardOperateResultActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" />

<!-- 订单列表Activity -->
<activity
android:name=".order.activity.OrderListActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />

<!-- 订单Services -->
<service android:name=".service.OrderService" />

<!-- 订单详情Activity -->
<activity
android:name=".order.activity.OrderDetailActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />

<activity
android:name=".paymanage.activity.RefundOrderActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden"
android:theme="@style/CustomActivityDialogStyle"/>
<activity
android:name=".paymanage.activity.OrderDetailInfoActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".printer.PosSettingActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />
<activity android:name=".pay.recharge.RechargeActivity" />
<activity android:name=".set.activity.ModeChangeActivity" />
<!-- 后结选桌Activity -->
<activity
android:name=".aftersettlement.activity.ChooseTableActivity"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden" />

<!-- 后结菜单Activity -->
<activity
android:name=".aftersettlement.activity.MenuActivity"
android:screenOrientation="landscape"
android:windowSoftInputMode="adjustPan" />
<activity
android:name=".aftersettlement.activity.PaymentActivity"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateHidden"/>
<activity
android:name=".paymanage.activity.PaymentDetailActivity"
android:windowSoftInputMode="stateHidden"/>
<activity
android:name=".pay.BankCardRefundActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoDisplay"
android:windowSoftInputMode="stateHidden"/>

</application>

</manifest>

+ 3
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CandidateAppInfo.aidl Ver fichero

@@ -0,0 +1,3 @@
package com.icbc.smartpos.deviceservice.aidl;

parcelable CandidateAppInfo;

+ 133
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CandidateAppInfo.java Ver fichero

@@ -0,0 +1,133 @@
/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package com.icbc.smartpos.deviceservice.aidl;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;

public class CandidateAppInfo implements Parcelable {
/**候选应用标识符(AID)*/
private byte[] tAID = new byte[16];
/**候选应用标签*/
private byte[] tAppLabel = new byte[16];
/**应用优先级指示符*/
private byte[] tAPN = new byte[16];
private byte cAPID;
private byte cFlgAPID;
/**语言参考*/
private byte[] sLangPref = new byte[8];
/**发行方证书索引*/
private byte cIssCTIndex;
private byte cFlgIssCTIndex;
public static final Creator<CandidateAppInfo> CREATOR = new Creator() {
public CandidateAppInfo createFromParcel(Parcel source) {
CandidateAppInfo appInfo = new CandidateAppInfo();

readByteArray(source.createByteArray(), appInfo.tAID);
readByteArray(source.createByteArray(), appInfo.tAppLabel);
readByteArray(source.createByteArray(), appInfo.tAPN);

appInfo.cAPID = source.readByte();
appInfo.cFlgAPID = source.readByte();

readByteArray(source.createByteArray(), appInfo.sLangPref);

appInfo.cIssCTIndex = source.readByte();
appInfo.cFlgIssCTIndex = source.readByte();
return appInfo;
}

public CandidateAppInfo[] newArray(int size) {
return new CandidateAppInfo[size];
}

private int getMinValue(int value1, int value2) {
return ((value1 > value2) ? value2 : value1);
}

private void readByteArray(byte[] source, byte[] dest) {
int arrayLen = 0;
arrayLen = getMinValue(source.length, dest.length);
System.arraycopy(source, 0, dest, 0, arrayLen);
}
};

public void setAID(byte[] aid) {
this.tAID = aid;
}

public byte[] getAID() {
return this.tAID;
}

public void setAppLabel(byte[] appLabel) {
this.tAppLabel = appLabel;
}

public byte[] getAppLabel() {
return this.tAppLabel;
}

public void setAPN(byte[] apn) {
this.tAPN = apn;
}

public byte[] getAPN() {
return this.tAPN;
}

public void setAPID(byte apid) {
this.cAPID = apid;
}

public byte getAPID() {
return this.cAPID;
}

public void setAPIDFlag(byte flag) {
this.cFlgAPID = flag;
}

public byte getAPIDFlag() {
return this.cFlgAPID;
}

public void setLangPref(byte[] langPref) {
this.sLangPref = langPref;
}

public byte[] getLangPref() {
return this.sLangPref;
}

public void setIssCTIndex(byte index) {
this.cIssCTIndex = index;
}

public byte getIssCTIndex() {
return this.cIssCTIndex;
}

public void setIssCTIndexFlag(byte flag) {
this.cFlgIssCTIndex = flag;
}

public byte getIssCTIndexFlag() {
return this.cFlgIssCTIndex;
}

public int describeContents() {
return 0;
}

public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(this.tAID);
dest.writeByteArray(this.tAppLabel);
dest.writeByteArray(this.tAPN);
dest.writeByte(this.cAPID);
dest.writeByte(this.cFlgAPID);
dest.writeByteArray(this.sLangPref);
dest.writeByte(this.cIssCTIndex);
dest.writeByte(this.cFlgIssCTIndex);
}
}

+ 52
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/CheckCardListener.aidl Ver fichero

@@ -0,0 +1,52 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 检卡过程监听接口定义
* @author: baoxl
*/
interface CheckCardListener {
/**
* 检测到磁条卡
* @param track - 磁卡数据
* <ul>
* <li>PAN(String) - 主账号(卡号)</li>
* <li>TRACK1(String) - 磁道1数据</li>
* <li>TRACK2(String) - 磁道2数据 </li>
* <li>TRACK3(String) - 磁道3数据</li>
* <li>SERVICE_CODE(String) - 服务码 </li>
* <li>EXPIRED_DATE(String) - 卡片有效期 </li>
* </ul>
*/
void onCardSwiped(in Bundle track);
/**
* IC卡上电成功
*/
void onCardPowerUp();
/**
* 非接卡激活成功
*/
void onCardActivate();
/**
* 检卡超时
*/
void onTimeout();
/**
* 检卡出错
* @param error - 错误码
* <ul>
* <li>SERVICE_CRASH(99) - 服务崩溃 </li>
* <li>REQUEST_EXCEPTION(100) - 请求异常</li>
* <li>MAG_SWIPE_ERROR(1) - 刷卡失败</li>
* <li>IC_INSERT_ERROR(2) - 插卡失败</li>
* <li>IC_POWERUP_ERROR(3) - 卡上电失败</li>
* <li>RF_PASS_ERROR(4) - 非接挥卡失败</li>
* <li>RF_ACTIVATE_ERROR(5) - 非接卡激活失败</li>
* </ul>
* @param message - 错误描述
*/
void onError(int error, String message);
}

+ 14
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/FontFamily.java Ver fichero

@@ -0,0 +1,14 @@
package com.icbc.smartpos.deviceservice.aidl;

public class FontFamily {
public static final int SMALL = 0;
public static final int MIDDLE = 1;
public static final int BIG = 2;
public static final boolean NEED_BOLD = true;
public static final boolean NOT_NEED_BOLD = false;
public static final int LEFT = 0;
public static final int CENTER = 1;
public static final int RIGHT = 2;
}

+ 21
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IBeeper.aidl Ver fichero

@@ -0,0 +1,21 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 蜂鸣器对象
* @author: baoxl
*/
interface IBeeper {
/**
* 开始蜂鸣<br/>
* 通过调用该方法可以让POS的蜂鸣器持续鸣叫msec毫秒。如果用户设定msec为0则不进行鸣叫。
* 蜂鸣器发声是采用非阻塞方式进行的,调用该函数之后,程序立即退出,不会停留在该函数。 
* @param msec - 需要鸣叫的时间,单位ms
*/
void startBeep(int msec);
/**
* 停止蜂鸣<br/>
* 调用该方法后立即停止鸣叫
*/
void stopBeep();
}

+ 102
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IDeviceInfo.aidl Ver fichero

@@ -0,0 +1,102 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.TusnData;

/**
* 终端设备信息对象
* @author: baoxl
*/
interface IDeviceInfo {
/**
* 获取终端序列号
* @return 终端设备序列号
*/
String getSerialNo();
/**
* 获取终端IMSI号
* @return 终端IMSI号
*/
String getIMSI();
/**
* 获取终端IMEI号
* @return 终端IMEI号
*/
String getIMEI();
/**
* 获取SIM卡ICCID
* @return 终端SIM卡ICCID
*/
String getICCID();
/**
* 获取厂商名称
* @return 终端厂商名称
*/
String getManufacture();
/**
* 获取终端设备型号
* @return 终端设备型号
*/
String getModel();
/**
* 获取终端Android操作系统版本
* @return 终端Android系统版本
*/
String getAndroidOSVersion();
/**
* 获取终端Android内核版本
* @return 终端Android内核版本
*/
String getAndroidKernelVersion();
/**
* 获取终端ROM版本
* @return 终端系统ROM版本
*/
String getROMVersion();
/**
* 获取终端固件版本
* @return 终端固件版本
*/
String getFirmwareVersion();
/**
* 获取终端硬件版本
* @return 终端硬件版本 -后标贴的硬件版本号,如H:L4200151361,测试机器可能没有录入
*/
String getHardwareVersion();
/**
* 更新终端系统时间
* @param date - 日期,格式yyyyMMdd
* @param time - 时间,格式HHmmss
* @return 更新成功返回true,失败返回false
**/
boolean updateSystemTime(String date, String time);
/**
* 设置系统功能(设置全局有效)
* @param bundle - 设置参数
* <ul>
* <li>HOMEKEY(boolean) – 是否允许使用HOME键,true可用,false禁用(注:在机器重启后会取消屏蔽)</li>
* <li>STATUSBARKEY(boolean) – 是否允许使用下拉菜单,true可用,false禁用</li>
* </ul>
* @return 设置成功返回true,失败返回false
**/
boolean setSystemFunction(in Bundle bundle);
/**
* 获取银联终端唯一终端号TUSN
* @param mode 模式, 预留参数, 需为0
* @param input 指 对TUSN计算 MAC 时,参与计算的随机数(随机因子),允许范围:4~10字节
* @return 成功返回TUSN数据,失败返回null。
**/
TusnData getTUSN(int mode, in byte[] input);
}

+ 88
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IDeviceService.aidl Ver fichero

@@ -0,0 +1,88 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.IBeeper;
import com.icbc.smartpos.deviceservice.aidl.IDeviceInfo;
import com.icbc.smartpos.deviceservice.aidl.ILed;
import com.icbc.smartpos.deviceservice.aidl.IMagCardReader;
import com.icbc.smartpos.deviceservice.aidl.IDeviceService;
import com.icbc.smartpos.deviceservice.aidl.IInsertCardReader;
import com.icbc.smartpos.deviceservice.aidl.IPBOC;
import com.icbc.smartpos.deviceservice.aidl.IPinpad;
import com.icbc.smartpos.deviceservice.aidl.IPrinter;
import com.icbc.smartpos.deviceservice.aidl.IRFCardReader;
import com.icbc.smartpos.deviceservice.aidl.IScanner;
import com.icbc.smartpos.deviceservice.aidl.ISerialPort;

/**
* 设备服务对象,提供范围终端各外设对象的服务接口
* @author: baoxl
*/
interface IDeviceService {
/**
* 获取蜂鸣器操作对象
* @return IBeeper对象,参见IBeeper.aidl类
*/
IBeeper getBeeper();
/**
* 获取LED灯操作对象
* @return ILed对象,参见ILed.aidl类
*/
ILed getLed();
/**
* 获取串口操作对象
* @return ISerialPort对象,参见ISerialPort.aidl类
*/
ISerialPort getSerialPort();
/**
* 获取扫码器操作对象
* @param cameraId - 0前置扫码器,1后置扫码器
* @return IScanner对象,参见IScanner.aidl类
*/
IScanner getScanner(int cameraId);

/**
* 获取磁卡操作句柄
* @return IMagCardReader对象,参见IMagCardReader.aidl类
*/
IMagCardReader getMagCardReader();
/**
* 获取IC卡操作对象
* @return IC卡操作对象,参见IInsertCardReader.aidl类
*/
IInsertCardReader getInsertCardReader();
/**
* 获取RF卡操作对象
* @return RF卡操作对象,参见IRFCardReader.aidl类
*/
IRFCardReader getRFCardReader();
/**
* 获取密码键盘操作对象
* @param kapId 密码键盘kapId索引,每个kapId对一个逻辑密码键盘
* @return IPinpad对象,参见IPinpad.aidl类
*/
IPinpad getPinpad(int kapId);
/**
* 获取打印机操作对象
* @return IPrinter对象,参见IPrinter.aidl类
*/
IPrinter getPrinter();
/**
* 获取PBOC(EMV)流程操作对象
* @return IPBOC对象,参见IPBOC.aidl类
*/
IPBOC getPBOC();
/**
* 设备操作对象
* @return IDeviceInfo对象,参见IDeviceInfo.aidl类
*/
IDeviceInfo getDeviceInfo();
}

+ 43
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IInsertCardReader.aidl Ver fichero

@@ -0,0 +1,43 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 接触式IC读卡器对象
* @author: baoxl
*/
interface IInsertCardReader {
/**
* 卡上电
* @return 上电成功true,上电失败false。
*/
boolean powerUp();
/**
* 卡下电
* @return 关闭成功true,失败false。
*/
boolean powerDown();
/**
* 卡片是否在位
* @return 卡在位true,卡不在位false。
*/
boolean isCardIn();
/**
* APDU数据通讯
* @param apdu - apdu数据
* @return 成功返回卡片应答数据,失败返回null。
*/
byte[] exchangeApdu(in byte[] apdu);
/**
* 卡片复位
* @param resetType - 复位类型
* <ul>
* <li>0- WARMRESET</li>
* <li>1- COLDRESET</li>
* </ul>
* @return 卡片复位应答数据。
*/
byte[] cardReset(int resetType);
}

+ 31
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ILed.aidl Ver fichero

@@ -0,0 +1,31 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 设备LED灯对象
* @author: baoxl
*/
interface ILed {
/**
* 点亮LED灯
* @param led - 灯标识
* <ul>
* <li> 1 - 蓝灯</li>
* <li> 2 - 黄灯</li>
* <li> 3 - 绿灯</li>
* <li> 4 - 红灯</li>
* </ul>
*/
void turnOn(int led);
/**
* 关闭LED灯
* @param led - 灯标识
* <ul>
* <li> 1 - 蓝灯</li>
* <li> 2 - 黄灯</li>
* <li> 3 - 绿灯</li>
* <li> 4 - 红灯</li>
* </ul>
*/
void turnOff(int led);
}

+ 21
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IMagCardReader.aidl Ver fichero

@@ -0,0 +1,21 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.MagCardListener;

/**
* 磁条卡刷卡器对象
* @author: baoxl
*/
interface IMagCardReader {
/**
* 等待刷卡,获取磁卡卡片的磁道数据
* @param timeout - 检卡超时时间(单位秒)
* @param listener - 磁卡刷卡监听器
*/
void searchCard(int timeout, MagCardListener listener);
/**
* 取消等待刷卡
*/
void stopSearch();
}

+ 213
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPBOC.aidl Ver fichero

@@ -0,0 +1,213 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.CheckCardListener;
import com.icbc.smartpos.deviceservice.aidl.UPCardListener;
import com.icbc.smartpos.deviceservice.aidl.PBOCHandler;
import com.icbc.smartpos.deviceservice.aidl.OnlineResultHandler;
import com.icbc.smartpos.deviceservice.aidl.CandidateAppInfo;

/**
* PBOC金融交易对象<br/>
* 用来处理金融卡相关的EMV交易流程。
* @author: baoxl
*/
interface IPBOC {
/**
* PBOC检卡
* @param cardOption - 支持的卡类型,磁条卡、IC卡和非接卡
* <ul>
* <li>supportMagCard(boolean) - 是否支持磁条卡</li>
* <li>supportICCard(boolean) - 是否支持IC卡</li>
* <li>supportRFCard(boolean) - 是否支持非接卡</li>
* </ul>
* @param timeout - 超时时间
* @param listener - 检卡结果监听器
*/
void checkCard(in Bundle cardOption, int timeout, CheckCardListener listener);
/**
* 停止PBOC检卡
*/
void stopCheckCard();
/**
* 读取手机芯片卡
* @param listener - 读卡结果监听器
*/
void readUPCard(UPCardListener listener);
/**
* 启动PBOC处理流程
* @param transType - 交易类型
* <ul>
* <li>EC_BALANCE(1) - 查询电子现金余额</li>
* <li>TRANSFER(2) - 转账</li>
* <li>EC_LOAD(3) - 指定账户圈存</li>
* <li>EC_LOAD_U(4) - 非制定账户圈存</li>
* <li>EC_LOAD_CASH(5) - 现金圈存/现金充值</li>
* <li>EC_LOAD_CASH_VOID(6) - 圈存撤销</li>
* <li>PURCHASE(7) - 消费</li>
* <li>Q_PURCHASE(8) - 快速支付</li>
* <li>CHECK_BALANCE(9) - 余额查询</li>
* <li>PRE_AUTH(10) - 预授权交易</li>
* <li>SALE_VOID(11) - 消费撤销</li>
* <li>SIMPLE_PROCESS(12) - 简易流程交易</li>
* <li>Q_QUERY(13) - qPBOC查询</li>
* </ul>
* @param intent - 请求数据
* <ul>
* <li>cardType(int):卡类型,CARD_INSERT(0)-接触式IC卡,CARD_RF(1)-非接触式卡</li>
* <li>authAmount(long):授权金额(交易金额)</li>
* <li>isSupportQ(boolean):是否支持QPBOC</li>
* <li>isSupportSM(boolean):是否支持国密</li>
* <li>isQPBOCForceOnline(boolean):QPBOC是否支持强制联机</li>
* <li>merchantName(String):商户名称</li>
* <li>merchantId(String):商户号</li>
* <li>terminalId(String):终端号</li>
* </ul>
* @param handler - PBOC流程回调处理器
*/
void startPBOC(int transType, in Bundle intent, PBOCHandler handler);
/**
* 终止PBOC流程
*/
void abortPBOC();

/**
* 更新AID参数
* @param operation - 操作标识,增、删、清空
* <ul>
* <li>1:新增 </li>
* <li>2:删除 </li>
* <li>3:清空 </li>
* </ul>
* @param aidType - AID参数类型
* <ul>
* <li>1:接触式 </li>
* <li>2:非接</li>
* </ul>
* @param aid - AID参数,构成AID参数的TLV字符串
* @return 成功true,失败false
*/
boolean updateAID(int operation,int aidType, String aid);

/**
* 获取当前aid参数TLV数据列表,在选择完应用后可以调用
* @param taglist - 需要获得的tag列表
* @return tlv数据,null表示没有数据
*/
String getAidParams(in String[] taglist);

/**
* 更新CA公钥参数
* @param operation - 操作标识,增、删、清空
* <ul>
* <li>1:新增 </li>
* <li>2:删除 </li>
* <li>3:清空 </li>
* </ul>
* @param rid - CA公钥参数
* @return 成功true,失败false
*/
boolean updateRID(int operation, String rid);
/**
* 导入金额
* @param amount - 交易金额
*/
void importAmount(long amount);
/**
* 导入应用选择结果(多应用卡片)
* @param index - 应用选择的序号从1开始,0为取消
*/
void importAppSelect(int index);
/**
* 导入PIN
* @param option(int) - 操作选项
* <ul>
* <li> CANCEL(0) - 取消 </li>
* <li> CONFIRM(1) - 确认 </li>
* </ul>
* @param pin - PIN数据
*/
void importPin(int option, in byte[] pin);
/**
* 导入身份认证结果
* @param option - 确认结果
* <ul>
* <li> CANCEL(0) - 取消,跳过(BYPASS) </li>
* <li> CONFIRM(1) - 确认持卡人身份 </li>
* <li> NOTMATCH(2) - 身份信息不符 </li>
* </ul>
*/
void importCertConfirmResult(int option);
/**
* 导入卡信息确认结果
* @param pass - 是否通过
*/
void importCardConfirmResult(boolean pass);
/**
* 导入联机应答数据
* @param onlineResult - 联机结果
* <ul>
* <li> isOnline(boolean) - 是否联机</li>
* <li> respCode(String) - 应答码</li>
* <li> authCode(String) - 授权码 </li>
* <li> field55(String) - 55域应答数据</li>
* </ul>
* @param handler - 联机结果处理
*/
void inputOnlineResult(in Bundle onlineResult, OnlineResultHandler handler);

/**
* 设置TLV内核参数
* @param tlvList 内置参数TLV列表
*/
void setEMVData(in List<String> tlvList);
/**
* 获取PBOC内核TLV数据列表
* @param taglist - 需要获得的tag列表
* @return tlv数据,null表示没有数据
*/
String getAppTLVList(in String[] taglist);
/**
* 获取卡片上EMV数据元
* @param tagName - 标签名称
* @return 卡片EMV数据
*/
byte[] getCardData(String tagName);
/**
* 获取PBOC流程数据,如卡号、有效期、卡片序列号等。<br/>
* <em>EMV必须执行到相应流程才能获取到对应的卡片数据,否则返回空。</em>
* @param tagName - 标签名称
* <ul>
* <li> PAN - 卡号</li>
* <li> TRACK2 - 磁道二数据</li>
* <li> CARD_SN - 卡片序列号 </li>
* <li> EXPIRED_DATE - 有效期</li>
* <li> DATE - 日期</li>
* <li> TIME - 时间</li>
* <li> BALANCE - 电子现金余额</li>
* <li> CURRENCY - 币种</li>
* </ul>
* @return PBOC流程中内核返回的数据
*/
String getPBOCData(String tagName);
/**
* 获取卡片候选应用信息<br/>
* 用于电子签名上送和小额免签免密。
* @return 卡片候选应用信息,具体见{@link CandidateAppInfo}定义
*/
CandidateAppInfo getCandidateAppInfo();
}

+ 113
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPinpad.aidl Ver fichero

@@ -0,0 +1,113 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.PinInputListener;

/**
* 密码键盘对象<br/>
* 实现金融交易过程中密钥管理、数据加密和PIN输入处理过程。
* @author: baoxl
*/
interface IPinpad {
/**
* 判断密钥是否存在(密钥已下载)<br/>
* @param keyType - 密钥类型
* <ul>
* <li>0-主密钥</li>
* <li>1-MAC密钥</li>
* <li>2-PIN密钥</li>
* <li>3-TD密钥</li>
* </ul>
* @param keyId - 密钥ID
* @return 存在返回true,不存在返回false
**/
boolean isKeyExist(int keyType, int keyId);
/**
* 下装TEK密钥<br/>
* TEK是加密主密钥的密钥KEK
* @param keyId - 密钥存储的ID
* @param key - 密钥
* @param checkValue - 校验值
* @return 成功true,失败false
*/
boolean loadTEK(int keyId, in byte[] key, in byte[] checkValue);
/**
* 下装密文主密钥<br/>
* @param keyId - 下装密钥存储ID
* @param key - 密钥
* @param checkValue - 校验值
* @return 成功true,失败false
*/
boolean loadEncryptMainKey(int keyId, in byte[] key, in byte[] checkValue);
/**
* 下装明文主密钥<br/>
* @param keyId - 下装密钥存储ID
* @param key - 密钥
* @param checkValue - 校验值
* @return 成功true,失败false
*/
boolean loadMainKey(int keyId, in byte[] key, in byte[] checkValue);
/**
* 下装工作密钥<br/>
* @param keyType - 下装工作密钥类型,1-MAC密钥,2-PIN密钥,3-TD密钥
* @param mkId - 解密工作密钥的主密钥ID
* @param keyId - 下装密钥存储ID
* @param key - 密钥
* @param checkValue - 校验值
* @return 成功true,失败false
*/
boolean loadWorkKey(int keyType, int mkId, int wkId, in byte[] key, in byte[] checkValue);
/**
* 计算MAC值<br/>
* @param keyId - MAC密钥索引
* @param data - 计算MAC的数据
* @return 成功返回mac值,失败返回null
*/
byte[] calcMAC(int keyId, in byte[] data);
/**
* 加密磁道数据<br/>
* @param mode - 加密模式
* @param keyId - TDK密钥索引
* @param trkData - 待加密磁道数据
* @return 成功返回加密后的磁道数据,失败返回null
*/
byte[] encryptTrackData(int mode, int keyId, in byte[] trkData);
/**
* 启动PIN输入<br/>
* @param keyId - PIN密钥索引
* @param param - PIN输入配置参数
* <ul>
* <li>pinLimit(byte[]) - 允许输入密码的长度</li>
* <li>timeout(int) - 输入超时时间,单位(秒)</li>
* <li>isOnline(boolean) - 是否联机PIN</li>
* <li>promptString(String) - 提示信息</li>
* <li>pan(String) - 用于加密联机PIN的主帐号(卡号)</li>
* </ul>
* @param listener - PIN输入过程监听器
* @return
*/
void startPinInput(int keyId, in Bundle param, PinInputListener listener);
/**
* 提交PIN输入
*/
void submitPinInput();
/**
* 取消PIN输入过程
*/
void stopPinInput();
/**
* 获取最近一次操作的错误<br/>
* @return 错误描述
*/
String getLastError();
}

+ 105
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IPrinter.aidl Ver fichero

@@ -0,0 +1,105 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.PrinterListener;

/**
* 打印机对象<br/>
* 实现对文本、条形码、二维码和图片的打印功能。
* @author: baoxl
*/
interface IPrinter {
/**
* 获取打印机状态
* @return 打印机状态
* <ul>
* <li>ERROR_NONE(0x00) - 状态正常</li>
* <li>ERROR_PAPERENDED(0xF0) - 缺纸,不能打印</li>
* <li>ERROR_HARDERR(0xF2) - 硬件错误</li>
* <li>ERROR_OVERHEAT(0xF3) - 打印头过热</li>
* <li>ERROR_BUFOVERFLOW(0xF5) - 缓冲模式下所操作的位置超出范围 </li>
* <li>ERROR_LOWVOL(0xE1) - 低压保护 </li>
* <li>ERROR_PAPERENDING(0xF4) - 纸张将要用尽,还允许打印(单步进针打特有返回值)</li>
* <li>ERROR_MOTORERR(0xFB) - 打印机芯故障(过快或者过慢)</li>
* <li>ERROR_PENOFOUND(0xFC) - 自动定位没有找到对齐位置,纸张回到原来位置 </li>
* <li>ERROR_PAPERJAM(0xEE) - 卡纸</li>
* <li>ERROR_NOBM(0xF6) - 没有找到黑标</li>
* <li>ERROR_BUSY(0xF7) - 打印机处于忙状态</li>
* <li>ERROR_BMBLACK(0xF8) - 黑标探测器检测到黑色信号</li>
* <li>ERROR_WORKON(0xE6) - 打印机电源处于打开状态</li>
* <li>ERROR_LIFTHEAD(0xE0) - 打印头抬起(自助热敏打印机特有返回值)</li>
* <li>ERROR_CUTPOSITIONERR(0xE2) - 切纸刀不在原位(自助热敏打印机特有返回值)</li>
* <li>ERROR_LOWTEMP(0xE3) - 低温保护或AD出错(自助热敏打印机特有返回值)</li>
* </ul>
*/
int getStatus();
/**
* 设置打印灰度
* @param gray - 打印灰度0~10
*/
void setGray(int gray);
/**
* 添加一行打印文本
* @param format - 打印字体格式
* <ul>
* <li>font(int) - 0:small, 1:normal, 2:large</li>
* <li>align(int) - 0:left, 1:center, 2:right</li>
* </ul>
* @param text - 打印文本
*/
void addText(in Bundle format, String text);
/**
* 添加条码打印
* @param format - 打印格式,可设置打印的位置、宽度、高度
* <ul>
* <li>align(int) - 0:left, 1:center, 2:right</li>
* <li>width(int) - 宽度</li>
* <li>height(int) - 高度</li>
* </ul>
* @param barcode - 条码内容
*/
void addBarCode(in Bundle format, in String barcode);
/**
* 添加二维码打印
* @param format - 打印格式,可设置打印的位置、期望高度
* <ul>
* <li>offset(int) - 打印起始位置 </li>
* <li>expectedHeight(int) - 期望高度</li>
* </ul>
* @param qrCode - 二维码内容
*/
void addQrCode(in Bundle format, String qrCode);
/**
* 添加图片打印
* @param format - 打印格式,可设置打印的位置、宽度、高度
* <ul>
* <li>offset(int) - 打印起始位置</li>
* <li>width(int) - 宽度</li>
* <li>height(int) - 高度</li>
* </ul>
* @param imageData - 图片数据
*/
void addImage(in Bundle format, in byte[] imageData);
/**
* 走纸
* @param lines - 行数
*/
void feedLine(int lines);
/**
* 启动打印
* @param listener - 打印结果监听器
*/
void startPrint(PrinterListener listener);
/**
* 启动打印(打印不清缓存)
* @param listener - 打印结果监听器
*/
void startSaveCachePrint(PrinterListener listener);
}

+ 127
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IRFCardReader.aidl Ver fichero

@@ -0,0 +1,127 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.RFSearchListener;

/**
* 非接触式IC读卡器对象
* @author: baoxl
*/
interface IRFCardReader {
/**
* 非接寻卡上电<br/>
* @param listener - 寻卡监听器
*/
void searchCard(RFSearchListener listener);
/**
* 停止寻卡操作
* @return 关闭成功true,失败false。
*/
void stopSearch();
/**
* 激活卡片<br/>
* @param driver - 驱动名称
* <ul>
* <li>"S50" - S50卡</li>
* <li>"S70" - S70卡</li>
* <li>"CPU" - CPU卡</li>
* <li>"PRO" - PRO、S5O_PRO、S70_PRO卡</li>
* </ul>
* @param responseData - 激活卡片应答数据
* @return 返回0表示激活成功,其他失败。
*/
int activate(String driver, out byte[] responseData);
/**
* 关闭设备,再次操作需从寻卡开始<br/>
*/
void halt();
/**
* 卡片是否在位
* @return 卡在位true,卡不在位false。
*/
boolean isExist();
/**
* APDU数据通讯
* @param apdu - apdu数据
* @return 成功返回卡片应答数据。
*/
byte[] exchangeApdu(in byte[] apdu);
/**
* 卡片复位
* @param resetType - 复位类型
* <ul>
* <li>0- WARMRESET</li>
* <li>1- COLDRESET</li>
* </ul>
* @return 卡片复位应答数据。
*/
byte[] cardReset(int resetType);
/**
* 认证(根据块号)
* <ul>
* <li>对卡执行读写,修改的操作时必须先进行认证,而且同时只能认证一个扇区,在对不同的扇区进行操作时需要再做认证。</li><br/>
* <li>该接口需要指定认证块的具体位置</li>
* </ul>
* @param blockNo 块号,从0开始
* @param keyType 密钥类型 KEY_A 或者 KEY_B
* @param key 密钥,6字节长
* @return 成功0x00,其他失败
*/
int authBlock(int blockNo, int keyType, in byte[] key);
/**
* 认证(根扇区号)<br/>
* <ul>
* <li>对卡执行读写,修改的操作时必须先进行认证,而且同时只能认证一个扇区,在对不同的扇区进行操作时需要再做认证。</li><br/>
* <li>该接口只需要指定要操作的扇区,会自动对该扇区的第3块(从0起)进行认证操作</li>
* </ul>
* @param sectorNo 扇区号,从0开始
* @param keyType 密钥类型 KEY_A 或者 KEY_B
* @param key 密钥,6字节长
* @return 成功0x00,其他失败
*/
int authSector(int sectorNo, int keyType, in byte[] key);
/**
* 读块数据
* @param blockNo - 块号
* @param data - 读取返回的块数据(16字节数据)
* @return 成功0x00,其他失败
*/
int readBlock(int blockNo, out byte[] data);
/**
* 写块数据<br/>
* <ul>
* <li>必须是16个字节的数据,没有达到字节数将认为是错误。</li>
* </ul>
* @param blockNo - 块号
* @param data - 指定数据写到指定的块里
* @return 成功0x00,其他失败
*/
int writeBlock(int blockNo, in byte[] data);
/**
* 加值</br>
* 把指定的值加至一数值块中<br/>
* @param blockNo - 块号
* @param value - 数据
* @return 成功0x00,其他失败
*/
int increaseValue(int blockNo, int value);
/**
* 减值</br>
* 从一数值块中减去指定的值<br/>
* @param blockNo - 块号
* @param value - 数据
* @return 成功0x00,其他失败
*/
int decreaseValue(int blockNo, int value);
}

+ 25
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/IScanner.aidl Ver fichero

@@ -0,0 +1,25 @@
package com.icbc.smartpos.deviceservice.aidl;

import com.icbc.smartpos.deviceservice.aidl.ScannerListener;

/**
* 扫码器对象<br/>
* 实现设备对二维码扫码功能。
* @author: baoxl
*/
interface IScanner {
/**
* 启动扫码
* @param配置参数
* upPromptString(String):扫描框上方提示信息,最大20汉字,默认中间对齐,
* downPromptString(String):扫描框下方提示信息,最大20汉字,默认中间对齐
* timeout - 超时时间,单位ms
* listener - 扫码结果监听
*/
void startScan(in Bundle param, long timeout, ScannerListener listener);
/**
* 停止扫码
*/
void stopScan();
}

+ 75
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ISerialPort.aidl Ver fichero

@@ -0,0 +1,75 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 串口设备对象<br/>
* 实现串口数据收发功能。
* @author: baoxl
*/
interface ISerialPort {
/**
* 打开串口
* @return 成功true,失败false
*/
boolean open();
/**
* 关闭串口
* @return 成功true,失败false
*/
boolean close();
/**
* 初始化串口
* @param bps 波特率
* <ul>
* <li>1200 - 对应1200波特率</li>
* <li>2400 - 对应2400波特率</li>
* <li>4800 - 对应4800波特率</li>
* <li>9600 - 对应9600波特率</li>
* <li>14400 - 对应14400波特率</li>
* <li>19200 - 对应19200波特率</li>
* <li>28800 - 对应28800波特率</li>
* <li>38400 - 对应38400波特率</li>
* <li>57600 - 对应57600波特率</li>
* <li>115200 - 对应115200波特率</li>
* </ul>
* @param par 效验
* <ul>
* <li>0 - 不校验</li>
* <li>1 - 奇校验</li>
* <li>2 - 偶校验</li>
* </ul>
* @param dbs 数据位
* @return 成功true,失败false
*/
boolean init(int bps, int par, int dbs);
/**
* 读数据(接收)
* @param buffer 缓冲区
* @param timeout 超时时间,毫秒
* @return 返回实际读取的数据长度,失败返回-1
*/
int read(inout byte[] buffer, int timeout);
/**
* 写数据(发送)
* @param data 要发送的数据
* @param timeout 超时时间,毫秒
* @return 返回实际写入的数据长度,失败返回-1
*/
int write(in byte[] data, int timeout);
/**
* 清除接收缓冲区
* @return 成功true,失败false
*/
boolean clearInputBuffer();
/**
* 查看缓冲区是否为空
* @param input true为输入缓冲区,false为输出缓冲区
* @return 成功true,失败false
*/
boolean isBufferEmpty(boolean input);
}

+ 38
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/MagCardListener.aidl Ver fichero

@@ -0,0 +1,38 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 磁条卡刷卡结果回调
* @author: baoxl
*/
interface MagCardListener {
/**
* 刷卡成功回调
* @param track - 磁卡数据对象
* <ul>
* <li>PAN(String) - 主账号(卡号)</li>
* <li>TRACK1(String) - 磁道1数据</li>
* <li>TRACK2(String) - 磁道2数据 </li>
* <li>TRACK3(String) - 磁道3数据</li>
* <li>SERVICE_CODE(String) - 服务码 </li>
* <li>EXPIRED_DATE(String) - 卡片有效期 </li>
* </ul>
*/
void onSuccess(in Bundle track);

/**
* 刷卡失败回调
* @param error - 错误码
* <ul>
* <li>SERVICE_CRASH(99) - 服务崩溃 </li>
* <li>REQUEST_EXCEPTION(100) - 请求异常</li>
* <li>MAG_SWIPE_ERROR(1) - 刷卡失败</li>
* </ul>
* @param message - 错误描述
*/
void onError(int error,String message );
/**
* 刷卡超时回调
*/
void onTimeout();
}

+ 30
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/OnlineResultHandler.aidl Ver fichero

@@ -0,0 +1,30 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* PBOC流程联机应答数据处理
* @author: baoxl
*/
interface OnlineResultHandler {
/**
* 联机应答数据处理回调<br/>
* @param result - 处理结果
* <ul>
* <li>ONLINE_RESULT_TC(0) - 联机成功 </li>
* <li>ONLINE_RESULT_AAC(1) - 联机拒绝 </li>
* <li>ONLINE_RESULT_OFFLINE_TC(101) - 联机失败,脱机成功 </li>
* <li>ONLINE_RESULT_SCRIPT_NOT_EXECUTE(102) - 脚本未执行 </li>
* <li>ONLINE_RESULT_SCRIPT_EXECUTE_FAIL(103) - 脚本执行失败 </li>
* <li>ONLINE_RESULT_NO_SCRIPT(104) - 联机失败,未下送脚本 </li>
* <li>ONLINE_RESULT_TOO_MANY_SCRIPT(105) - 联机失败,脚本超过1个 </li>
* <li>ONLINE_RESULT_TERMINATE(106) - 联机失败,交易终止(GAC返回非9000,要提示交易终止,0x8F) </li>
* <li>ONLINE_RESULT_ERROR(107) - 联机失败,EMV内核错误</li>
* </ul>
* @param data - 结果数据
* <ul>
* <li>TC_DATA(String) - 交易结果TLV数据 </li>
* <li>SCRIPT_DATA(String) - 脚本结果TLV数据 </li>
* <li>REVERSAL_DATA(String) - 冲正TLV数据 </li>
* </ul>
*/
void onProccessResult(int result, in Bundle data);
}

+ 100
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PBOCHandler.aidl Ver fichero

@@ -0,0 +1,100 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* PBOC交易流程回调接口
* @author: baoxl
*/
interface PBOCHandler {
/**
* 请求输入金额
*/
void onRequestAmount();
/**
* 请求应用选择
* @param appList - 应用列表
*/
void onSelectApplication(in List<String> appList);
/**
* 要求确认卡信息
* @param info - 卡片信息
* <ul>
* <li>PAN(String) - 主账号(卡号)</li>
* <li>TRACK2(String) - 磁道2数据 </li>
* <li>CARD_SN(String) - 卡片序列号 </li>
* <li>SERVICE_CODE(String) - 服务码 </li>
* <li>EXPIRED_DATE(String) - 卡片有效期 </li>
* </ul>
*/
void onConfirmCardInfo(in Bundle info);
/**
* 要求输入PIN
* @param isOnlinePin 是否是联机pin
* @param retryTimes 脱机pin的输入次数
*/
void onRequestInputPIN(boolean isOnlinePin, int retryTimes);
/**
* 要求确认持卡人证件
* @param certType - 认证类型
* @param certInfo - 认证信息
*/
void onConfirmCertInfo(String certType, String certInfo);
/**
* 联机处理请求
* @param aaResult 卡片分析结果,联机数据
* <ul>
* <li>RESULT(int) - 结果类型:QPBOC_ARQC(201) - qPBOC联机请求; AARESULT_ARQC(2) - 行为分析结果ARQC</li>
* <li>ARQC_DATA(String) - 联机请求卡片55域数据 </li>
* <li>REVERSAL_DATA(String) - IC卡冲正TLV数据 </li>
* </ul>
*/
void onRequestOnlineProcess(in Bundle aaResult);
/**
* PBOC交易结果,见于简易流程,qPBOC,以及交易过程失败等
* @param result - 交易结果
* <ul>
* <li>EMV_COMPLETE(9) - EMV简易流程结束 </li>
* <li>EMV_ERROR(11) - EMV内核错误</li>
* <li>EMV_FALLBACK(12) - FALLBACK </li>
* <li>EMV_DATA_AUTH_FAIL(13) - 脱机数据认证失败 </li>
* <li>EMV_APP_BLOCKED(14) - 应用被锁定 </li>
* <li>EMV_NOT_ECCARD(15) - 非电子现金卡 </li>
* <li>EMV_UNSUPPORT_ECCARD(16) - 该交易不支持电子现金卡 </li>
* <li>EMV_AMOUNT_EXCEED_ON_PURELYEC(17) - 纯电子现金卡消费金额超限 </li>
* <li>EMV_SET_PARAM_ERROR(18) - 参数设置错误(9F7A) </li>
* <li>EMV_PAN_NOT_MATCH_TRACK2(19) - 主账号与二磁道不符 </li>
* <li>EMV_CARD_HOLDER_VALIDATE_ERROR(20) - 持卡人认证失败 </li>
* <li>EMV_PURELYEC_REJECT(21) - 纯电子现金卡被拒绝交易 </li>
* <li>EMV_BALANCE_INSUFFICIENT(22) - 余额不足 </li>
* <li>EMV_AMOUNT_EXCEED_ON_RFLIMIT_CHECK(23) - 交易金额超过非接限额检查 </li>
* <li>EMV_CARD_BIN_CHECK_FAIL(24) - 卡BIN检查失败 </li>
* <li>EMV_CARD_BLOCKED(25) - 卡被锁 </li>
* <li>EMV_MULTI_CARD_ERROR(26) - 多卡冲突 </li>
* <li>EMV_BALANCE_EXCEED(27) - 余额超出 </li>
* <li>EMV_RFCARD_PASS_FAIL(60) - 挥卡失败 </li>
* <li>EMV_IN_QPBOC_PROCESS(99) - QPBOC流程处理中 </li>
*
* <li>AARESULT_TC(0) - 行为分析结果,交易批准(脱机)</li>
* <li>AARESULT_AAC(1) - 行为分析结果,交易拒绝 </li>
* <li>QPBOC_AAC(202) - qPBOC交易结果,交易拒绝</li>
* <li>QPBOC_ERROR(203) - qPBOC交易结果,交易失败 </li>
* <li>QPBOC_TC(204) - qPBOC交易结果,交易批准 </li>
* <li>QPBOC_CONT(205) - qPBOC结果,转接触式卡 </li>
* <li>QPBOC_NO_APP(206) - qPBOC交易结果,无应用(可转UP Card)</li>
* <li>QPBOC_NOT_CPU_CARD(207) - qPBOC交易结果,该卡非TYPE B/PRO卡</li>
* </ul>
*
* @param data 交易结果数据
* <ul>
* <li>TC_DATA(String) - IC卡交易批准卡片返回数据 </li>
* <li>REVERSAL_DATA(String) - IC卡冲正数据 </li>
* <li>ERROR(String) - 错误描述(PBOC流程错误返回) </li>
* </ul>
*/
void onTransactionResult(int result, in Bundle data);
}

+ 32
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PinInputListener.aidl Ver fichero

@@ -0,0 +1,32 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* PIN输入过程监听器
* @author: baoxl
*/
interface PinInputListener {
/**
* 按键按压事件
* @param len - 已输入密码长度
* @param key - 当前的Key值
*/
void onInput(int len, int key);
/**
* 用户确认PIN输入时调用
* @param data - pin码,输入为空时候,为null
* @param isNonePin - 输入为空的时候为true
*/
void onConfirm(in byte[] data, boolean isNonePin);

/**
* 取消PIN输入时调用
*/
void onCancel();
/**
* 错误时回调
* @param errorCode - 错误码
*/
void onError(int errorCode);
}

+ 16
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PinpadKeyType.java Ver fichero

@@ -0,0 +1,16 @@
package com.icbc.smartpos.deviceservice.aidl;

public class PinpadKeyType{
// ABC中密钥类型0: MASTER KEY
public static final int MASTERKEY = 0;
//1:MAC key
public static final int MACKEY = 1;
// 2:PIN key
public static final int PINKEY = 2;
//3:TDK key
public static final int TDKEY = 3;
}

+ 10
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PrinterConfig.java Ver fichero

@@ -0,0 +1,10 @@
package com.icbc.smartpos.deviceservice.aidl;

public class PrinterConfig {
/**字体,默认小字体**/
public static final String BUNDLE_PRINT_FONT = "font";
/**对齐方式,默认左对齐**/
public static final String BUNDLE_PRINT_ALIGN = "align";
}

+ 18
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/PrinterListener.aidl Ver fichero

@@ -0,0 +1,18 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 打印结果监听器
* @author: baoxl
*/
interface PrinterListener {
/**
* 打印成功回调
*/
void onFinish();
/**
* 打印失败回调
* @param error - 错误码
*/
void onError(int error);
}

+ 37
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/RFSearchListener.aidl Ver fichero

@@ -0,0 +1,37 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 非接寻卡过程监听接口定义
* @author: baoxl
*/
interface RFSearchListener {
/**
* 检测到磁条卡
* @param cardType - 卡类型
* <ul>
* <li>S50_CARD(0x00) - S50卡</li>
* <li>S70_CARD(0x01) - S70卡</li>
* <li>PRO_CARD(0x02) - PRO卡</li>
* <li>S50_PRO_CARD(0x03) - 支持S50驱动与PRO驱动的PRO卡</li>
* <li>S70_PRO_CARD(0x04) - 支持S70驱动与PRO驱动的PRO卡 </li>
* <li>CPU_CARD(0x05) - CPU卡</li>
* </ul>
*/
void onCardPass(int cardType);
/**
* 寻卡失败回调
* @param error - 错误码
* <ul>
* <li>ERROR_TRANSERR(0xA2) - 通讯错误 </li>
* <li>ERROR_PROTERR(0xA3) - 卡片返回数据不符合规范要求</li>
* <li>ERROR_MULTIERR(0xA4) - 感应区内多卡存在</li>
* <li>ERROR_CARDTIMEOUT(0xA7) - 超时无响应</li>
* <li>ERROR_CARDNOACT(0xB3) - Pro卡或者TypeB卡未激活</li>
* <li>ERROR_MCSERVICE_CRASH(0xff01) - 主控服务异常</li>
* <li>ERROR_REQUEST_EXCEPTION(0xff02) - 请求异常</li>
* </ul>
* @param message - 错误描述
*/
void onFail(int error, String message);
}

+ 30
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/ScannerListener.aidl Ver fichero

@@ -0,0 +1,30 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 扫码器扫码结果监听器
* @author: baoxl
*/
interface ScannerListener {
/**
* 扫码成功回调
* @param barcode - 条码
*/
void onSuccess(String barcode);
/**
* 扫码出错
* @param error - 错误码
* @param message - 错误描述
*/
void onError(int error, String message);
/**
* 扫码超时回调
*/
void onTimeout();
/**
* 扫码取消回调
*/
void onCancel();
}

+ 3
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/TusnData.aidl Ver fichero

@@ -0,0 +1,3 @@
package com.icbc.smartpos.deviceservice.aidl;

parcelable TusnData;

+ 75
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/TusnData.java Ver fichero

@@ -0,0 +1,75 @@
package com.icbc.smartpos.deviceservice.aidl;

import android.os.Parcel;
import android.os.Parcelable;

/**
* TUSN数据
* @author baoxl
*
*/
public class TusnData implements Parcelable {
public static final Parcelable.Creator<TusnData> CREATOR = new Parcelable.Creator<TusnData>() {
@Override
public TusnData createFromParcel(Parcel source) {
return new TusnData(source);
}

@Override
public TusnData[] newArray(int size) {
return new TusnData[size];
}
};

/** 终端类型: 1为旧终端 2为新终端 */
private int mTerminalType;
/** 使用终端TUSN_AUK对传入随机数与TUSN进行MAC运算的结果,对于旧终端,为8个空格 */
private String mMac;
/** 唯一终端序列号 */
private String mTusn;
protected TusnData(Parcel source) {
mTerminalType = source.readInt();
mMac = source.readString();
mTusn = source.readString();
}
public TusnData() {}
public void setTerminalType(int type) {
mTerminalType = type;
}
public void setMac(String mac) {
mMac = mac;
}
public void setTusn(String tusn) {
mTusn = tusn;
}
public String getMac() {
return mMac;
}
public String getTusn() {
return mTusn;
}
public int getTerminalType() {
return mTerminalType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mTerminalType);
dest.writeString(mMac);
dest.writeString(mTusn);
}
}

+ 35
- 0
app/src/main/aidl/com/icbc/smartpos/deviceservice/aidl/UPCardListener.aidl Ver fichero

@@ -0,0 +1,35 @@
package com.icbc.smartpos.deviceservice.aidl;

/**
* 读手机芯片卡结果监听器
* @author: baoxl
*/
interface UPCardListener {
/**
* 读卡成功回调
* @param data - 芯片卡卡数据
* <ul>
* <li>PAN(String) - 主账号(卡号)</li>
* <li>TRACK2(String) - 磁道2数据 </li>
* <li>TRACK3(String) - 磁道3数据</li>
* <li>CARD_SN(String) - 卡片序列号</li>
* <li>EXPIRED_DATE(String) - 卡片有效期 </li>
* <li>TLV_DATA(String) - 带标签(DF32,DF33,DF34)TLV数据</li>
* </ul>
*/
void onRead(out Bundle data);
/**
* 读卡错误回调
* @param error - 错误码
* <ul>
* <li>ERROR_DETECT_CARD(1) - 识别卡失败</li>
* <li>ERROR_READ_SN(2) - 读卡序列号失败</li>
* <li>ERROR_READ_TRACK(3) - 读卡信息失败</li>
* <li>ERROR_SERVICE_CRASH(4) - 设备服务异常</li>
* <li>ERROR_NULL_DRIVER(5) - 非接驱动为null</li>
* </ul>
* @param message - 错误描述
*/
void onError(int error, String message);
}

+ 15
- 0
app/src/main/aidl/com/icbc/smartpos/transservice/aidl/ITransService.aidl Ver fichero

@@ -0,0 +1,15 @@
package com.icbc.smartpos.transservice.aidl;

import com.icbc.smartpos.transservice.aidl.TransHandler;

/**
* 交易调用接口
* @author: icbc
*/
interface ITransService {

long startTrans(String transType,
in Bundle ctrlData,
in Bundle transData,
in TransHandler handler);
}

+ 10
- 0
app/src/main/aidl/com/icbc/smartpos/transservice/aidl/TransHandler.aidl Ver fichero

@@ -0,0 +1,10 @@
package com.icbc.smartpos.transservice.aidl;

/**
* 交易流程回调接口
* @author: icbc
*/
interface TransHandler {

void onFinish(in Bundle baseResult, in Bundle transResult, in Bundle extraInfo);
}

+ 115
- 0
app/src/main/aidl/com/unionpay/CloudPosPaymentClient/aidl/ICloudPay.aidl Ver fichero

@@ -0,0 +1,115 @@
package com.unionpay.CloudPosPaymentClient.aidl;

interface ICloudPay{
//-----------收单----------
//消费
String payCash(String jsonData);
//交易查询
String getPayInfo(String jsonData);
//获取终端信息
String getPOSInfo(String jsonData);
//签到
String signIn(String jsonData);
//批结算
String settlement(String jsonData);
//余额查询
String balanceQuery(String jsonData);
//消费撤销
String consumeCancel(String jsonData);
//账户验证
String accountVerify(String jsonData);
//交易统计
String dealStatics(String jsonData);
//交易明细查询
String detailQuery(String jsonData);
//退货
String returnGoods(String jsonData);
//-----------多渠道----------
//建立委托
String createCommission(String jsonData);
//撤销委托
String undoCommission(String jsonData);
//单笔代收
String singleCollection(String jsonData);
//实时代付
String payForAnother(String jsonData);
//代付确认
String payConfirm(String jsonData);
//单笔限额和单日限额查询
String limitQuery();
//单笔限额和单日限额设置
String limitSet(String jsonData);
//剩余限额查询
String limitLeft();
//结算统计
String dealStatistics(String jsonData);
// 信用卡还款
String creditCardPayment(String jsonData);
// 转帐
String transfer(String jsonData);
// 手机充值
String phoneRecharge(String jsonData);
//单笔撤消
String cancelSingleCollection(String jsonData);
//水电煤缴费
String billPayment(String jsonData);
//账单查询
String billQuery(String jsonData);
//终端激活
String getAppTerms();
//-----------UPOP----------
// 代收
String takeCollection(String data);
// 代付
String takePayment(String data);
// 交易撤销
String cancelTransaction(String data);
// 交易查询
String queryTransaction(String data);
// 文件传输类交易
String transactByFile(String data);
// 代收控制交易
String cancelControl(String data);
//--------贷款类---------
// 贷款查询
String loanQuery(String jsonData);
// 贷款试算
String loanCal(String jsonData);
// 贷款还款
String loanPayment(String jsonData);
// 社保缴费
String tipsLevyAgent(String jsonData);
//助农取款
String withDrawal(String jsonData);
//--------贷款类二期--------
// 帐单费用查询
String billQueryServlet(String jsonData);
// 缴费有密
String billPaymentServletWithPin(String jsonData);
// 缴费无密
String billPaymentServletWithoutPin(String jsonData);
//--------银联钱包2.0--------
// 增值服务消费(先查后消费)
String walletSec(String jsonData);
// 增值服务撤销
String walletSecRevoke(String jsonData);
// 增值服务退货
String walletSecReturn(String jsonData);
//单笔限额和单日限额查询,支持应用商户号
String limitQueryWithAppInfo(String jsonData);
//剩余限额查询
String limitLeftWithAppInfo(String jsonData);
//扫码付接口
String scanPay(String jsonData);
}

+ 7
- 0
app/src/main/aidl/com/unionpay/facepay/IFacePayInterface.aidl Ver fichero

@@ -0,0 +1,7 @@
package com.unionpay.facepay;

import com.unionpay.facepay.IFacePayListener;

interface IFacePayInterface {
boolean facePay(String payInfo, IFacePayListener listener);
}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio

Cargando…
Cancelar
Guardar