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