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 }