package moe.yuuta.ext; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import androidx.annotation.NonNull; import moe.yuuta.gplicense.util.Base64; import moe.yuuta.gplicense.util.Base64DecoderException; public interface IService extends IInterface { abstract class Stub extends Binder implements IService { private static final String DESCRIPTOR; static { try { // Base64 encoded - // com.android.vending.licensing.ILicensingService DESCRIPTOR = new String(Base64.decode( "Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")); } catch (Base64DecoderException e) { throw new RuntimeException(e); } } public Stub() { this.attachInterface(this, DESCRIPTOR); } public static IService asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (iin instanceof IService) { return (IService) iin; } return new IService.Stub.Proxy(obj); } @Override public IBinder asBinder() { return this; } @Override public boolean onTransact(int code, @NonNull Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_checkLicense: { data.enforceInterface(DESCRIPTOR); long nonce = data.readLong(); String packageName = data.readString(); IResultListener listener = IResultListener.Stub.asInterface(data.readStrongBinder()); this.exec(nonce, packageName, listener); return true; } default: { return super.onTransact(code, data, reply, flags); } } } private static class Proxy implements IService { private IBinder mRemote; Proxy(IBinder remote) { mRemote = remote; } @Override public IBinder asBinder() { return mRemote; } @Override public void exec(long nonce, String packageName, IResultListener listener) throws RemoteException { Parcel args = Parcel.obtain(); try { args.writeInterfaceToken(DESCRIPTOR); args.writeLong(nonce); args.writeString(packageName); args.writeStrongBinder(listener != null ? listener.asBinder() : null); mRemote.transact(TRANSACTION_checkLicense, args, null, IBinder.FLAG_ONEWAY); } finally { args.recycle(); } } } static final int TRANSACTION_checkLicense = IBinder.FIRST_CALL_TRANSACTION; } // checkLicense void exec(long nonce, String packageName, IResultListener listener) throws RemoteException; }