diff options
Diffstat (limited to 'dom/system/gonk/VolumeCommand.h')
-rw-r--r-- | dom/system/gonk/VolumeCommand.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/dom/system/gonk/VolumeCommand.h b/dom/system/gonk/VolumeCommand.h new file mode 100644 index 000000000..022965b5e --- /dev/null +++ b/dom/system/gonk/VolumeCommand.h @@ -0,0 +1,204 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_system_volumecommand_h__ +#define mozilla_system_volumecommand_h__ + +#include "nsString.h" +#include "nsISupportsImpl.h" +#include "mozilla/RefPtr.h" +#include <algorithm> +#include <vold/ResponseCode.h> + +namespace mozilla { +namespace system { + +class Volume; +class VolumeCommand; + +/*************************************************************************** +* +* The VolumeResponseCallback class is an abstract base class. The ResponseReceived +* method will be called for each response received. +* +* Depending on the command, there may be multiple responses for the +* command. Done() will return true if this is the last response. +* +* The responses from vold are all of the form: +* +* <ResponseCode> <String> +* +* Valid Response codes can be found in the vold/ResponseCode.h header. +* +***************************************************************************/ + +class VolumeResponseCallback +{ +protected: + virtual ~VolumeResponseCallback() {} + +public: + NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback) + VolumeResponseCallback() + : mResponseCode(0), mPending(false) {} + + bool Done() const + { + // Response codes from the 200, 400, and 500 series all indicated that + // the command has completed. + + return (mResponseCode >= ::ResponseCode::CommandOkay) + && (mResponseCode < ::ResponseCode::UnsolicitedInformational); + } + + bool WasSuccessful() const + { + return mResponseCode == ::ResponseCode::CommandOkay; + } + + bool IsPending() const { return mPending; } + int ResponseCode() const { return mResponseCode; } + const nsCString &ResponseStr() const { return mResponseStr; } + +protected: + virtual void ResponseReceived(const VolumeCommand* aCommand) = 0; + +private: + friend class VolumeCommand; // Calls HandleResponse and SetPending + + void HandleResponse(const VolumeCommand* aCommand, + int aResponseCode, + nsACString& aResponseStr) + { + mResponseCode = aResponseCode; +#if ANDROID_VERSION >= 17 + // There's a sequence number here that we don't care about + // We expect it to be 0. See VolumeCommand::SetCmd + mResponseStr = Substring(aResponseStr, 2); +#else + mResponseStr = aResponseStr; +#endif + if (mResponseCode >= ::ResponseCode::CommandOkay) { + // This is a final response. + mPending = false; + } + ResponseReceived(aCommand); + } + + void SetPending(bool aPending) { mPending = aPending; } + + int mResponseCode; // The response code parsed from vold + nsCString mResponseStr; // The rest of the line. + bool mPending; // Waiting for response? +}; + +/*************************************************************************** +* +* The VolumeCommand class is an abstract base class used to encapsulate +* volume commands send to vold. +* +* See VolumeManager.h for a list of the volume commands. +* +* Commands sent to vold need an explicit null character so we add one +* to the command to ensure that it's included in the length. +* +* All of these commands are asynchronous in nature, and the +* ResponseReceived callback will be called when a response is available. +* +***************************************************************************/ + +class VolumeCommand +{ +protected: + virtual ~VolumeCommand() {} + +public: + NS_INLINE_DECL_REFCOUNTING(VolumeCommand) + + VolumeCommand(VolumeResponseCallback* aCallback) + : mBytesConsumed(0), + mCallback(aCallback) + { + SetCmd(NS_LITERAL_CSTRING("")); + } + + VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback) + : mBytesConsumed(0), + mCallback(aCallback) + { + SetCmd(aCommand); + } + + void SetCmd(const nsACString& aCommand) + { + mCmd.Truncate(); +#if ANDROID_VERSION >= 17 + // JB requires a sequence number at the beginning of messages. + // It doesn't matter what we use, so we use 0. + mCmd = "0 "; +#endif + mCmd.Append(aCommand); + // Add a null character. We want this to be included in the length since + // vold uses it to determine the end of the command. + mCmd.Append('\0'); + } + + const char* CmdStr() const { return mCmd.get(); } + const char* Data() const { return mCmd.Data() + mBytesConsumed; } + size_t BytesConsumed() const { return mBytesConsumed; } + + size_t BytesRemaining() const + { + return mCmd.Length() - std::min(mCmd.Length(), mBytesConsumed); + } + + void ConsumeBytes(size_t aNumBytes) + { + mBytesConsumed += std::min(BytesRemaining(), aNumBytes); + } + +private: + friend class VolumeManager; // Calls SetPending & HandleResponse + + void SetPending(bool aPending) + { + if (mCallback) { + mCallback->SetPending(aPending); + } + } + + void HandleResponse(int aResponseCode, nsACString& aResponseStr) + { + if (mCallback) { + mCallback->HandleResponse(this, aResponseCode, aResponseStr); + } + } + + nsCString mCmd; // Command being sent + size_t mBytesConsumed; // How many bytes have been sent + + // Called when a response to the command is received. + RefPtr<VolumeResponseCallback> mCallback; +}; + +class VolumeActionCommand : public VolumeCommand +{ +public: + VolumeActionCommand(Volume* aVolume, const char* aAction, + const char* aExtraArgs, VolumeResponseCallback* aCallback); + +private: + RefPtr<Volume> mVolume; +}; + +class VolumeListCommand : public VolumeCommand +{ +public: + VolumeListCommand(VolumeResponseCallback* aCallback); +}; + +} // system +} // mozilla + +#endif // mozilla_system_volumecommand_h__ |