/* 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 #include 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: * * * * 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 mCallback; }; class VolumeActionCommand : public VolumeCommand { public: VolumeActionCommand(Volume* aVolume, const char* aAction, const char* aExtraArgs, VolumeResponseCallback* aCallback); private: RefPtr mVolume; }; class VolumeListCommand : public VolumeCommand { public: VolumeListCommand(VolumeResponseCallback* aCallback); }; } // system } // mozilla #endif // mozilla_system_volumecommand_h__