github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/am/am.go (about)

     1  package am
     2  
     3  import (
     4  	"github.com/racerxdl/gonx/nx/env"
     5  	"github.com/racerxdl/gonx/nx/nxerrors"
     6  	"github.com/racerxdl/gonx/nx/nxtypes"
     7  	"github.com/racerxdl/gonx/services/ipc"
     8  	"github.com/racerxdl/gonx/services/sm"
     9  	"github.com/racerxdl/gonx/svc"
    10  	"time"
    11  )
    12  
    13  var debug = false
    14  var amInitializations = 0
    15  var proxyServiceObject ipc.Object
    16  var proxyObject ipc.Object
    17  var iSelfControllerObject ipc.Object
    18  var iWindowController ipc.Object
    19  var amDomain *ipc.Domain
    20  
    21  func GetObject(iface ipc.Object, command int) (ipc.Object, error) {
    22  	if amInitializations <= 0 {
    23  		return ipc.Object{}, nxerrors.AMNotInitialized
    24  	}
    25  
    26  	rq := ipc.MakeDefaultRequest(uint32(command))
    27  	rs := ipc.ResponseFmt{}
    28  	rs.Objects = make([]ipc.Object, 1)
    29  
    30  	err := ipc.Send(iface, &rq, &rs)
    31  	if err != nil {
    32  		return ipc.Object{}, err
    33  	}
    34  
    35  	return rs.Objects[0], nil
    36  }
    37  
    38  func Init() (err error) {
    39  	if debug {
    40  		println("am::Init()")
    41  	}
    42  	amInitializations++
    43  	if amInitializations > 1 {
    44  		return nil
    45  	}
    46  
    47  	proxyServiceInit := false
    48  	domainInit := false
    49  	iscInit := false
    50  	proxyInit := false
    51  
    52  	defer func() {
    53  		if err != nil {
    54  			amInitializations--
    55  			if iscInit {
    56  				_ = ipc.Close(&iSelfControllerObject)
    57  			}
    58  			if proxyInit {
    59  				_ = ipc.Close(&proxyObject)
    60  			}
    61  			if proxyServiceInit {
    62  				_ = ipc.Close(&proxyServiceObject)
    63  			}
    64  			if domainInit {
    65  				_ = ipc.CloseSession(amDomain.Session)
    66  				amDomain = nil
    67  			}
    68  		}
    69  		sm.Finalize()
    70  	}()
    71  
    72  	err = sm.Init()
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	appletType := env.GetAppletType()
    78  
    79  	switch appletType {
    80  	case nxtypes.AppletTypeDefault:
    81  		appletType = nxtypes.AppletTypeApplication
    82  		fallthrough
    83  	case nxtypes.AppletTypeApplication:
    84  		err = sm.GetService(&proxyServiceObject, "appletOE")
    85  	default:
    86  		err = sm.GetService(&proxyServiceObject, "appletAE")
    87  	}
    88  
    89  	if err != nil {
    90  		return err
    91  	}
    92  	proxyServiceInit = true
    93  
    94  	amDomain, err = ipc.ConvertToDomain(&proxyServiceObject)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	domainInit = true
    99  
   100  	cmdId := uint32(0)
   101  	switch appletType {
   102  	case nxtypes.AppletTypeApplication:
   103  		cmdId = 0
   104  	case nxtypes.AppletTypeSystemApplet:
   105  		cmdId = 100
   106  	case nxtypes.AppletTypeLibraryApplet:
   107  		cmdId = 200
   108  	case nxtypes.AppletTypeOverlayApplet:
   109  		cmdId = 300
   110  	case nxtypes.AppletTypeSystemApplication:
   111  		cmdId = 350
   112  	default:
   113  		return nxerrors.UnknownAppletType
   114  	}
   115  
   116  	// Open Application Proxy
   117  	rq := ipc.Request{}
   118  	rs := ipc.ResponseFmt{}
   119  	resCode := uint64(nxerrors.AMBusy)
   120  	for resCode == nxerrors.AMBusy {
   121  		rq = ipc.MakeDefaultRequest(cmdId)
   122  		rq.SetRawDataFromUint64(0)
   123  		rq.SendPID = true
   124  		rq.CopyHandles = []nxtypes.Handle{svc.CurrentProcessHandle}
   125  
   126  		rs = ipc.ResponseFmt{}
   127  		rs.Objects = make([]ipc.Object, 1)
   128  
   129  		err = ipc.Send(proxyServiceObject, &rq, &rs)
   130  		if err != nil {
   131  			ipcErr, ok := err.(nxerrors.IPCError)
   132  			if !ok || ipcErr.Result != nxerrors.AMBusy {
   133  				return err
   134  			}
   135  
   136  			time.Sleep(time.Second)
   137  		} else {
   138  			resCode = 0
   139  		}
   140  	}
   141  
   142  	proxyObject = rs.Objects[0]
   143  	proxyInit = true
   144  
   145  	iSelfControllerObject, err = GetObject(proxyObject, 1)
   146  	if err != nil {
   147  		return err
   148  	}
   149  	iscInit = true
   150  
   151  	iWindowController, err = GetObject(proxyObject, 2)
   152  	return err
   153  }
   154  
   155  func forceFinalize() {
   156  	if debug {
   157  		println("am::ForceFinalize()")
   158  	}
   159  
   160  	_ = ipc.Close(&iWindowController)
   161  	_ = ipc.Close(&iSelfControllerObject)
   162  	_ = ipc.Close(&proxyObject)
   163  	_ = ipc.Close(&proxyServiceObject)
   164  
   165  	if amDomain != nil {
   166  		_ = ipc.CloseSession(amDomain.Session)
   167  		amDomain = nil
   168  	}
   169  	amInitializations = 0
   170  }
   171  
   172  func Finalize() {
   173  	if debug {
   174  		println("am::Finalize()")
   175  	}
   176  	amInitializations--
   177  	if amInitializations <= 0 {
   178  		forceFinalize()
   179  	}
   180  }