-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: OSVR on Android - server auto start vs shared service app #433
Comments
Chase here, from Razer, providing my two cents. Apologies for the incoming wall of text. :) Having the community weigh in is a great idea! Now let’s break the approaches down and provide as many facts as possible. I would like to add as a side note that both approaches below have an “auto-start” component to the proposal, but they handle the implementation in different ways. Auto-start API (JointClientKit Approach?) Another pitfall for the JointClientKit approach, especially on mobile, of the server running in the same process (which can be duplicated by backgrounding an app and starting a new one) is that it will consume more resources (compute/power/thermal/memory) than a single instance running in as a service. This also means it will duplicate data in a user’s device storage and possibly reduce the number of applications they can install. A couple things previously mentioned that are worth discussing :
Bound Android Service I’d like to make a few more clarifications to points previously made :
Both approaches are similar at their core, as I see it. The key differences being :
I am definitely in favor of the bound service approach on Android. In my opinion, it provides ease of use for developers and end-users. They only need to worry about the client application and we take care of the rest. It is also the most future-proof, since it uses Android APIs to sandbox, manage permissions, and handle resources that may very between devices and android versions. It is also worth clarifying, are you suggesting the move to JointClientKit for all platforms? If not, how should a developer treat the same client code when moving between desktop and mobile platforms? |
Thank you Chase for taking the time to post and for working on this. To clarify, what I am advocating for is sort of a hybrid model. I think it is very important that OSVR applications work independently of each other and of any shared applications we might deploy (e.g. for configuration). It should also be easy for developers to integrate into their app - as easy as the Cardboard SDK is now. Although I understand the desire to make OSVR-Android more like the PC/Mac/Linux version in terms of having an independent server app, I think you vastly underestimate the negative effect of a separate app hard requirement would have on any OSVR apps - both from users and from developers. It's important to remember that Android is not like a desktop operating system, and you need to think of the ecosystem differently. I can tell you with certainty that few experienced or high-end Android developera are going to go for a separate app requirement. The vast majority of users simply will not go through the hassle of installing another app after installing your app. They'll just downrate the app, write a nasty comment, and then uninstall your app without playing it. It just isn't done in serious apps. The best you can hope for is an optional requirement - the way that the Cardboard SDK works. That is, your SDK works just fine on its own, but may be enhanced by another app that provides shared services or configuration. Secondly, a few clarifications/responses to your post:
Keep in mind that we are competing against three SDKs on android. The first two are the Cardboard SDK and the GearVR SDK. The Cardboard SDK comes in a self-contained bundle of libraries, which also support a shared configuration (to "pair" the SDK with the current viewer). This is exactly what I'm proposing for OSVR by default. The GearVR SDK works more like what you're describing, but in that case the developer can count on the services already being installed, because they have OS/Hardware level integration, which we don't, and because they need it to be installed to download gearvr apps in the first place, which we can't count on. The third SDK is going to be whatever Google provides for AndroidVR or whatever they end up calling it. It will be even easier to integrate because it will be built-into the SDK itself. If our SDK ends up being a pain to use compared to these alternatives, developers simply won't bother. |
OSVR has a responsibility to allow third party hardware manufacturers to update their plugins and issue hotfixes. The JointClientKit approach creates complexity for maintenance of plugins for hardware developers. This means they have no control over the perception of their products in this model because hardware plugin fixes, and updates, may never make their way into the applications. The Google Cardboard SDK is not so different from the implementation I am in favor of. It also requires an additional application, the Cardboard app, in order for an end user to change viewer configurations. It uses the Cardboard app as a service to manage configurations. I have searched the play store for user reviews that needlessly downvoted applications because of the need for an external application, but found none. Also, developers don’t seem to mind it. The “shared configuration” is a single protobuf file that multiple clients can use to calculate their distortion correction meshes at runtime, and is forced in Cardboard. Cardboard also uses sensor manager (an Android service) to poll the IMU and provide their 3DOF estimations. Cardboard doesn’t work with sensors directly like we do. They also poll Android for screen intrinsics to allow some other functionalities. They work with a few Android services and ship a client library, much like my proposal. As a quick recap:
Given the evidence above, I don’t think there would be a developer/end-user objection to using the bound service model. Cardboard and GearVR both use something similar. It is easy for developers of both hardware and software, as well as end-users. I also to discuss regressions and our test/release approach. It was never implied that we should test every released OSVR application with each OSVR server release. The reason we don’t need to test every application is that we already have access to the APIs used by those applications, and we can test those. If an application exposes an edge case, then we fix it and issue a hotfix that can be live within just a few hours. At the end of the day, if we are confident in the stability of the APIs this shouldn’t be this big of a concern. Unless hard facts have been officially released by Google about any AndroidVR projects, lets avoid speculating. |
The technical points outlined above by Chase are valid and should be examined closer. Behind it all, however, I think we might want to get back to the core of the discussion, which is the architectural implications. As I see it, there are a few different stake holders involved:
What works best for this collective set of stakeholders and how will we know if we’ve done the right thing (as sometimes our personal views don’t necessarily represent those of the target – an easy trap to fall into) is best determined by collecting some data.
In all cases, it might be prudent to get some real requirements from these stakeholders before forming a final position. Michael |
Thanks Michael, Chase. I think we are starting to align towards a solution that meets everyone's needs. I'll try to explain what I mean: To clarify, I am not opposed to having optional services and apps, including services from OEMs and peripheral developers that host their own OSVR plugins. For example, there were plans in place to have a shared server configuration file along with an OSVR config utility that enabled users to change server configuration (including adding "external" devices from other OSVR servers, including potentially from a local service on the same device). I am only opposed to making that application required for the app to run at all. The Cardboard SDK works like this. Cardboard SDK apps are self-contained in this sense. If you uninstall the Cardboard app, cardboard apps continue to function. You can also install cardboard apps without the cardboard app installed. Yes, the Cardboard app is required to pair cardboard apps with your cardboard viewer, and I'm OK with that for OSVR as well (see above comments about the plans for an OSVR-Config app for Android). But, if you don't have the app installed, Cardboard apps will continue to work with reasonable defaults. Some apps prompt users to install the cardboard app if it's not installed when you press the gear button in the middle, but it's optional. Like I said, I'm OK with optional apps that enhance or extend existing OSVR apps (either for configuration or adding additional plugins from OEMs or peripheral developers) as long as they are optional, and preferably auto-configured if possible. The only plugins I would bundle with the OSVR-Android SDK would be plugins that use official Android SDK APIs and built-in services. For these plugins (like the android sensor plugin or the imager plugin), the Android OS acts as a hardware abstraction layer and hardware OEMs can update their drivers at the OS level. For other plugins, such as those that might talk directly to a device connected locally to USB, the idea is that you'd expose those to OSVR apps as an external device. For OEM developers and peripheral developers, I think we can meet their needs a slightly different way. Instead of running a centralized OSVR server service, or running multiple OSVR server instances and using the external devices functionality to expose those devices to OSVR apps, you could instead write a kind of android "plug-and-play" system. This would be a plugin that works a little like the external devices functionality already built-in, but would be more automatic and require no pre-configuration. The idea is that OEMs and peripheral developers could wrap their OSVR plugins in a thin service just like the one you created to run the server (we could provide the boilerplate code - they just need to write an OSVR plugin just like normal). Then, you'd have a global registry that OEM developers could add their background services to. The plugin on the client app side would then dynamically register those devices at runtime and handle talking over the binder interfaces to each of them. This way, multiple stakeholders could install their own custom OSVR plugin services (not just the OEM or the OSVR team distributing the OSVR app in the play store), and there's less overhead than running multiple server instances and talking over IP loopback. I think this represents a decent "hybrid" solution that addresses everyone's needs. |
The approaches that you are suggesting do represent a possible solution to the matter at hand. However, you are suggesting a departure from the architectural design of the system for the other platforms. If a single server/app approach were the best solution from the user’s perspective for initial deployment, then we would have to seriously consider extending this same approach for the other platforms. Because of this, I am not OK proceeding just yet. Regarding management of deployment of the peripheral device interface components, distributing these as separate mini-services or even separate components could make the end user’s system much more difficult to manage and we’d have to be very careful how we manage data bandwidth across whatever boundaries. In fact, some of the recent discussions that we’ve been having with device manufacturers have them exploring methods with us to achieve tighter integration for the purposes of lower system latency as well as code management on their side. The message that we have gotten is that ideally they have OSVR to provide the infrastructure to deploy their device interface components without developing and maintaining their own service. The distribution and update of components and the core server is a complex problem that needs careful attention. Based on the open questions (and design tradeoffs) that are being surfaced, I think that is prudent to have a proper requirements doc and design vetted by the community before any further changes get checked into the main branch. This should be the standard we set for all OSVR submissions. Michael |
I have tried to follow the Android discussion with the main objective being to have OSVR HDK 1.3 run on the attached Razer Forge TV (Android TV) device. Lee T. Davy |
The aggregation plugin proposal isn't going against the the general architecture of OSVR. It's expected that some platforms may require special circumstances. Implementing those special circumstances as a plugin would probably be the least intrusive and recommended way to implement this functionality, as opposed to, for example, implementing a custom VRPN connection type on Android that uses the binder interface. Also, there are already other similar plugins that aggregate devices from other sources. For example, the SteamVR plugin aggregates any devices with OpenVR plugins. The multi-server plugin aggregates a few devices that we have "built-in" support for (HDK, Hydras, etc...). So a plugin on Android that aggregates devices from a special central registry (or alternatively from a single external app, if that is preferred given the performance or startup/shutdown requirements - it's up to the OEM), then that is not "out of the ordinary" for OSVR, and wouldn't lead to changes to the way we handle OSVR on other platforms. |
@CoolGames Thanks for your feedback! The Forge TV (and other standalone android devices like shield TV or similar custom hardware) is an important use case for OSVR and is something we are actively working on. |
I have noticed activity @JeroMiya in the builds, but nothing towards an integrated solution that was coming about two months ago as well support for the internal IMU. I have had repeated success with the server and your Android demo on NVIDIA Shield except for an IMU. I was told I could connect to it via a VRPN, but I feel this would not be ideal direction to go for orientation tracking and chose to use a separate USB based IMU with an Android library. Ideally it would be great to be able to plug it in and the HDK 1.3 external IMU replaces internal Google sensors (or in the Shield TV add them) so the headset could be used with Google Cardboard or the upcoming Google VR. In fact it seems to make more sense to just skip the OSVR layer completely and rely on Google VR, which has the ability to talk to other sensors. As mentioned, the screen works great on its own albeit no distortion or chromatic correction, timewarp, or low persistence mode. But none of these are available in the current OSVR Android server either (or at least a month ago) Anyway, I do hope we are looking at Google VR and if so, let me know and I will be will to help test and implement anything you are working on with Nexus 6P, Pixel C, and towards the end of the month the Shield TV. |
Hello @mebalzer, @russell-taylor is currently working on RenderManager for Android this month, and I've done some work on fixing up the C API for RM-OpenGL, so things are coming along on that front. There isn't currently an android driver for the HDK that makes it appear as a generic IMU to the OS (which would allow the GoogleVR SDK or our own OSVR-IMU plugin to work with it out of the box). What's missing is an alternate OSVR plugin for Android that uses app-space APIs to talk to the HDK over USB. @chase-cobb may be able to comment on the status of that project, if any. The current plugin uses a private API to talk to the USB device, but unless the app is "rooted" the OS will prevent the plugin from talking to the HDK (this is true whether the server is embedded with the client or you install a centralized server app). So for instance, if you wanted to setup a shield TV that works with the HDK, you'd have to build your own custom image with modifications to start the OSVR server as a init.rc daemon with the appropriate SELinux permissions. Obviously this isn't ideal, which is why a more "android-native" approach to USB is needed for the HDK. As for Google VR: I'd like to incorporate it as a supported OSVR plugin, maybe even replace the current sensor tracker plugin I wrote as a kind of stop-gap. I would welcome community contributions on this - though let me start a new github issue with some details I'd like to flesh out before work begins (such as enabling GVR context sharing between the plugin and the client app, so you can continue to use their audio SDK at the same time as OSVR). |
@mebalzer here is the new GoogleVR plugin issue: OSVR/OSVR-Android-Plugins#1 |
@chase-cobb So, I think we need to come to a conclusion on this decision soon. I was thinking of modifying my earlier proposal so that we can support all of the use cases we've identified. That is, the server auto-start functionality would do the following: Auto-start logic on Android:
Client Context Startup:
This will allow a single app binary to work in different environments:
|
@JeroMiya I agree that a decision must be made. Provided the discussion above, I still believe that the bound service is the only way to go without fragmenting the user base. While there could be a perceived benefit to the JointClientKit model at startup, it also works as a silent failure-case for people that haven’t installed the proper Service. This could easily cause fragmentation in the ecosystem, and removed the ability for new hardware developers to reach the entire OSVR user base. This also has a high chance of preventing software improvements in the server from reaching the full user base and puts the burden of server updates on the client developer. Also, in the bound service approach, the server only runs when a client application is foregrounded and bound to the Service. It would fail any pseudo-code that checks to see if the server is running before attempting to bind to the Service. As a quick recap of what has been said so far : Some of the measurable benefits to the Service approach
Perceived downsides to the Service approach
Downloading a single free APK from the Play store is simple and painless. The Service could, alternatively, be pre-installed by a device manufacturer as a turnkey solution. This seems to be less of an imposition that any other platform supported currently by OSVR, and it doesn't sacrifice the scalability of the platform. |
A few counterpoints:
Also, I failed to mention this before, but there are going to be special cases where you MUST run the server in-process. Initially, this will include GearVR apps (Oculus store requirements dictate you must use their SDK for tracking and the compositor, which we can accommodate with the in-process server), but may include the GoogleVR SDK (client has to share a context for the audio portion of the SDK, and maybe the compositor). |
Hi All, bringing these issues to the surface is great. However, resolving this topic requires a discussion with the different stakeholders (other partners, product management, and engineering) and we would be better served in a venue where we can collectively review the requirements, design, and implementation. All of these topics must also be treated within the context of the other platform targets to ensure consistency across the board. The decision is best made when we have consensus by as many of the community members as possible. We're listening. |
Some developer feedback against a separate server: OSVR/OSVR-AndroidServerLauncher#4 |
Apologies for crashing the party after the lengthy discussion. I got here referred from one of my requests to make the android OSVR server launch automatically with a client application to avoid having the end users running multiple applications. My two cents is that it is paramount that the end users do as little configuration as humanly possible -ideally they should be good to go with just downloading the client app (game, etc.). I am not sure which of the options here would be preferred, but I just wanted to highlight that the way it seems to work now -having to configure, download and run a separate server on android before running any OSVR app- is tremendously overkill. From an app/plugin/asset developer's perspective, being able to start the server from within the app seems the most sensible way forward, though I must confess I do not have the full picture in front of me and I do not fully understand the consequences of the server running as a service of the client application. I will spend some time going backwards on this conversation and see if I can offer any useful comments. Thanks all! |
Hi @Bundenth, thanks for the response. Just a quick word about the service. It only requires a user to install it and they don't have to run it themselves, ever. It starts automatically in the background when a client application starts. If you have used GearVR, it is very similar in approach. I encourage you to read the entire thread to get a better understanding of both proposals and ask clarifying questions if needed. This is an open discussion. 👍 I'll leave this link to bound services in Android so you can read more, if it helps. :) |
Yep, and just to clarify, the discussion has morphed since it started. Right now the two sides overlap. Here's a summary: Side 1: Bound Service ONLY
Side 2: Bound Service, if available, else in-process server fallback
Both Side 1 and Side 2:
|
Thanks for the summary! It seems there will be a bound service on both options -which is much better than the separate server app at the moment. The only discussion seems to be on whether or not to have the extra option to run an in-process server -for which I do not have a strong opinion, though from a user perspective, having a default functionality without the need of installing is always appealing, but perhaps the cons outweight this single pro. |
The bound service will exist in a separate app, not in the OSVR client app. It would work just like the current OSVR_AndroidServerLauncher app, except it will use a more efficient bound service instead of IP loopback. Option 2 with the in-process server fallback is the only way to get out of the separate app requirement. I'll edit the summary to make this clear. |
Hello everyone, I am coming from a bit different background than what has been presented here so far. For us it is important to be able to use an external OSVR server with a mobile client, not having them collocated on the mobile device. We are using Android HMDs and tablets together with external tracking systems and using OSVR to serve also metadata to the application. I have not seen much attention being paid to supporting this use case yet and, in fact, there is my still unmerged but closed (?) pull req for it: #331 While I recognize that hosting an OSVR server directly on the device is useful, there are also plenty of use cases where it actually complicates things, especially with the complicated configuration from a file - e.g. how can the user application tell the server which configuration to load, for example? Two applications could need different aliases, coordinate transformations or talk to an external server. There is no API for that at the moment - everything for every possible application has to be either hardwired in the config file or autodetected at runtime (impossible for many things). So if the server is encapsulated on the device as e.g. a service, this will need to be addressed. Many Android devices like GearVR or tablets have limited external connectivity (and most hw doesn't talk Bluetooth), so assuming that any controllers/peripherals or trackers will be directly connected to the device and autodetected is very limiting. Another common situation is that the middleware needed to make a certain device work is supported only in Windows (SDKs ...), so making a plugin for Android is not even an option. In these cases talking to an external server that combines the various devices is much simpler than trying to configure the internal one for relaying the data from the external one (and to uselessly add latency and complexity while losing information). Can this use case be considered as a first class citizen, please? |
@janoc Thanks for contributing! A couple of points: The osvr_server_config.json is not intended to contain application specific configuration, including aliases or transformations. The user needs to be in control of this at the server level, not the application level. My recommendation for this at the application level is to introduce a layer of abstraction where you can setup your own aliases and transformations on top of what comes from the client kit natively. Maybe this is something we could support at the client kit level? It's possible. It's a little out of scope, maybe. OSVR was intended to support distributed servers through the external devices mechanism. When you configure an external device, the client kit connects to that server directly, bypassing the local server. In your case, your local server would have no plugins, and you can set your polling time super high, so that the OSVR server consumes no CPU resources. As for bypassing the local server completely and connecting to a remote server, I think I remember there being an undocumented workaround for this involving environment variables but I don't remember the details. We don't recommend this for most users, so it's sort of a special one-off workaround. If that's not working on Android, we can maybe look into a different way to do it (a server config option perhaps). |
Hello Jeremy, I think you didn't understand my point about the server config. My point is that if the configuration is managed on the server that is running as a shared service, then the application needs to be able to tell the server to load or change to a specific configuration (e.g. containing an external device connection or some parameters). Right now there is no way for the client to tell the server to do so and the application is at the mercy of whatever the server has configured or autodetects. That is like demanding that 3 games from different vendors agree on a common way of configuring I/O - ain't happening if one expects milimeters and Y-up and another meters and Z-up, for example. Re external devices - this works unfortunately only at the level of VRPN connections. As far as I know, there is no way to fully forward the OSVR connection to an external OSVR server (preserving the access to the device tree metadata, aliases, etc. of the remote server). That is of limited utility. The undocumented workaround is the OSVR_HOST env variable, but that is that - a kludgy workaround. Unfortunately there is no official, non-kludgy way of doing it (apart from using the low level API which exposes it, for some reason), so we are maintaining a local set of patches adding this functionality. It does work on Android, but this kind of basic thing should be supported out of the box, IMHO. OSVR strives to be a superset of VRPN, so it should at least support the most common VRPN use cases properly. |
@janoc Yes, I agree that the OSVR_HOST env variable is a little kludgy. If we're going to support a particular scenario (e.g. telling client kit a specific host/port to connect to for the server), it should be through API or configuration and not hidden workarounds, and then use documentation to tell developers "warning - this API is for a specific use case, for all other usage, do this other thing". Regarding configuration swapping, I should have clarified - server configuration selection (or live switching) is outside of the scope for the ClientKit. That's a bit more server/client coupling than I'm comfortable with and it could potentially cause havoc. That doesn't mean you're out of luck, but it does mean you'll need an alternative means to implement the switching or live reloading. Perhaps a supervisor process on your server machine that responds to requests over the network by starting or restarting the server with a specific configuration. Then your client applications can make those requests prior to initializing the client context. |
@JeroMiya Well, the host/port is supported already, all it needs is a trivial patch in the ClientKit which I have submitted some time ago to expose it. Re documentation - I think the design philosophy behind the server and how to use it for various use cases should be better documented in general. That could potentially avoid some of these discussions. Re config switching - perhaps it shouldn't be in the ClientKit itself but a separate specialized API, no problem with that. However, an unified framework that would permit the client (or even a completely separate application - think control panel/dashboard) to demand some control things from the server would be very useful to have. I am thinking about stuff like loading of a specified config or asking the server to restart, for example and also to make sure that e.g. the server gets restarted if it crashes or is registered to start on boot (e.g. registering as a service on Android and in Windows, SystemD in Linux, etc). This is especially useful for people writing portable applications between desktop and e.g. Android. Abstracting the platform-specific complexities (e.g. process or config management) would make the life of the developer a lot simpler and help prevent the inevitable emergence of various hacks because the most common uses will be covered. It is one of my major beefs with deploying VRPN - good tool, but this type of "practicalities" were not handled at all and required various ad-hoc solutions. |
Hi, I was directed to this thread by OSVR DevRel. I'm new to OSVR, but if you are looking for input here are some thoughts from a developer's POV, in no particular order.
I hope that makes some sense. Happy to be challenged on any of that. Ash |
Currently on Android, OSVR has an implementation of the server auto-start API that starts a server in-process with the client app. The server runs in its own thread. It does not require a java layer to initiate - the same C++ code on Android will work on PC/Mac/Linux.
Chase Cobb from Razer recently announced some work he's done on an OSVR service that handles the OSVR server:
https://www.reddit.com/r/OSVR/comments/4iq4vz/osvr_android_update_02102016/
This issue is to discuss the two approaches and get community feedback, as well as to document decisions going forward. The current plan for OSVR on Android is for client apps to use the auto-start API as a black-box to ensure the server is running. The implementation would be to start the server in the same process (preferably using a memory stream instead of IP looback for the VRPN connection) in its own thread. The server would then look in a shared location, or use a binder, to access a shared server configuration if it exists, or fall back to a reasonable default configuration. The benefits to this approach are that the same C++ code works on Android as it does on PC/Mac/Linux. It also keeps client applications self-contained and stable - only optionally taking advantage of a shared configuration. It's more friendly to users, who are no longer required to download a separate app to get a VR app to work. It's more battery friendly - if you close an OSVR app, you can be sure that the server isn't still running in the background.
The shared service/app is the alternative. In this approach, the server runs as an Android service. It requires client apps to use a Java layer to initiate the connection to the server. OSVR apps depend on the OSVR app/service being installed to work, and must require the user to download the app if not already installed. The OSVR service app can be updated independently of client applications, which may break existing applications not tested on newer server versions. Depending on how the scheduler is tuned on a given Android device (they all differ in this regard), the background service may be punished if it takes up too much resources relative to the current foreground app, which may result in additional latency and hitches. The imaging plugin for Android cannot work with a shared service/app as it currently uses a special in-process-memory VRPN message type that only works when the server is in the same process as the client. The binder API is not intended for very large amounts of data, so the imager cannot be adapted to run over the binder interface.
I am heavily leaning towards the original plan - the in-process server thread started by the auto-start API. Feel free to discuss.
The text was updated successfully, but these errors were encountered: