blob: a443265c55f8e46e44ef73ec8188b30f67c56fb8 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H
#define ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H
#include <aidl/android/media/TranscodingSessionPriority.h>
#include <media/ControllerClientInterface.h>
#include <media/ResourcePolicyInterface.h>
#include <media/TranscoderInterface.h>
#include <media/TranscodingRequest.h>
#include <media/UidPolicyInterface.h>
#include <utils/String8.h>
#include <utils/Vector.h>
#include <chrono>
#include <list>
#include <map>
#include <mutex>
namespace android {
using ::aidl::android::media::TranscodingResultParcel;
using ::aidl::android::media::TranscodingSessionPriority;
class TranscodingSessionController : public UidPolicyCallbackInterface,
public ControllerClientInterface,
public TranscoderCallbackInterface,
public ResourcePolicyCallbackInterface {
public:
virtual ~TranscodingSessionController();
// ControllerClientInterface
bool submit(ClientIdType clientId, SessionIdType sessionId, uid_t uid,
const TranscodingRequestParcel& request,
const std::weak_ptr<ITranscodingClientCallback>& clientCallback) override;
bool cancel(ClientIdType clientId, SessionIdType sessionId) override;
bool getSession(ClientIdType clientId, SessionIdType sessionId,
TranscodingRequestParcel* request) override;
// ~ControllerClientInterface
// TranscoderCallbackInterface
void onStarted(ClientIdType clientId, SessionIdType sessionId) override;
void onPaused(ClientIdType clientId, SessionIdType sessionId) override;
void onResumed(ClientIdType clientId, SessionIdType sessionId) override;
void onFinish(ClientIdType clientId, SessionIdType sessionId) override;
void onError(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) override;
void onProgressUpdate(ClientIdType clientId, SessionIdType sessionId,
int32_t progress) override;
void onResourceLost(ClientIdType clientId, SessionIdType sessionId) override;
// ~TranscoderCallbackInterface
// UidPolicyCallbackInterface
void onTopUidsChanged(const std::unordered_set<uid_t>& uids) override;
// ~UidPolicyCallbackInterface
// ResourcePolicyCallbackInterface
void onResourceAvailable() override;
// ~ResourcePolicyCallbackInterface
/**
* Dump all the session information to the fd.
*/
void dumpAllSessions(int fd, const Vector<String16>& args);
private:
friend class MediaTranscodingService;
friend class TranscodingSessionControllerTest;
using SessionKeyType = std::pair<ClientIdType, SessionIdType>;
using SessionQueueType = std::list<SessionKeyType>;
struct Session {
enum State {
INVALID = -1,
NOT_STARTED = 0,
RUNNING,
PAUSED,
FINISHED,
CANCELED,
ERROR,
};
SessionKeyType key;
uid_t uid;
int32_t lastProgress;
int32_t pauseCount;
std::chrono::time_point<std::chrono::system_clock> stateEnterTime;
std::chrono::microseconds waitingTime;
std::chrono::microseconds runningTime;
std::chrono::microseconds pausedTime;
TranscodingRequest request;
std::weak_ptr<ITranscodingClientCallback> callback;
// Must use setState to change state.
void setState(Session::State state);
State getState() const { return state; }
private:
State state = INVALID;
};
// TODO(chz): call transcoder without global lock.
// Use mLock for all entrypoints for now.
mutable std::mutex mLock;
std::map<SessionKeyType, Session> mSessionMap;
// uid->SessionQueue map (uid == -1: offline queue)
std::map<uid_t, SessionQueueType> mSessionQueues;
// uids, with the head being the most-recently-top app, 2nd item is the
// previous top app, etc.
std::list<uid_t> mUidSortedList;
std::list<uid_t>::iterator mOfflineUidIterator;
std::map<uid_t, std::string> mUidPackageNames;
std::shared_ptr<TranscoderInterface> mTranscoder;
std::shared_ptr<UidPolicyInterface> mUidPolicy;
std::shared_ptr<ResourcePolicyInterface> mResourcePolicy;
Session* mCurrentSession;
bool mResourceLost;
std::list<Session> mSessionHistory;
// Only allow MediaTranscodingService and unit tests to instantiate.
TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
const std::shared_ptr<UidPolicyInterface>& uidPolicy,
const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
void dumpSession_l(const Session& session, String8& result, bool closedSession = false);
Session* getTopSession_l();
void updateCurrentSession_l();
void removeSession_l(const SessionKeyType& sessionKey, Session::State finalState);
void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
void notifyClient(ClientIdType clientId, SessionIdType sessionId, const char* reason,
std::function<void(const SessionKeyType&)> func);
// Internal state verifier (debug only)
void validateState_l();
static String8 sessionToString(const SessionKeyType& sessionKey);
static const char* sessionStateToString(const Session::State sessionState);
};
} // namespace android
#endif // ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H