Repo Created
This commit is contained in:
parent
eb305e2886
commit
a8c22c65db
4784 changed files with 329907 additions and 2 deletions
54
play-services-cast-framework/build.gradle
Normal file
54
play-services-cast-framework/build.gradle
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'signing'
|
||||
|
||||
android {
|
||||
namespace "com.google.android.gms.cast.framework"
|
||||
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
buildFeatures {
|
||||
aidl = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionName version
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../gradle/publish-android.gradle'
|
||||
|
||||
description = 'microG implementation of play-services-cast-framework'
|
||||
|
||||
dependencies {
|
||||
// Dependencies from play-services-cast-framework:21.2.0
|
||||
api 'androidx.appcompat:appcompat:1.0.0'
|
||||
api 'androidx.collection:collection:1.0.0'
|
||||
api 'androidx.concurrent:concurrent-futures:1.1.0'
|
||||
api 'androidx.core:core:1.0.0'
|
||||
api 'androidx.fragment:fragment:1.0.0'
|
||||
api 'androidx.media:media:1.6.0'
|
||||
api 'androidx.mediarouter:mediarouter:1.3.0'
|
||||
api 'androidx.recyclerview:recyclerview:1.0.0'
|
||||
// com.google.android.datatransport:transport-api:3.0.0
|
||||
// com.google.android.datatransport:transport-backend-cct:3.1.3
|
||||
// com.google.android.datatransport:transport-runtime:3.1.3
|
||||
api project(':play-services-base')
|
||||
api project(':play-services-basement')
|
||||
api project(':play-services-cast')
|
||||
api project(':play-services-tasks')
|
||||
api 'com.google.guava:listenablefuture:1.0'
|
||||
}
|
||||
56
play-services-cast-framework/core/build.gradle
Normal file
56
play-services-cast-framework/core/build.gradle
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'signing'
|
||||
|
||||
dependencies {
|
||||
implementation project(':play-services-cast-framework')
|
||||
implementation project(':play-services-base-core')
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "org.microg.gms.cast.framework.core"
|
||||
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
defaultConfig {
|
||||
versionName version
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
dataBinding = true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = 1.8
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../../gradle/publish-android.gradle'
|
||||
|
||||
description = 'microG service implementation for play-services-cast-framework'
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.mediarouter.media.MediaControlIntent;
|
||||
import androidx.mediarouter.media.MediaRouteSelector;
|
||||
|
||||
import com.google.android.gms.cast.CastMediaControlIntent;
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.IAppVisibilityListener;
|
||||
import com.google.android.gms.cast.framework.ICastContext;
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManager;
|
||||
import com.google.android.gms.cast.framework.ISessionManager;
|
||||
import com.google.android.gms.cast.framework.ISessionProvider;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CastContextImpl extends ICastContext.Stub {
|
||||
private static final String TAG = CastContextImpl.class.getSimpleName();
|
||||
|
||||
private SessionManagerImpl sessionManager;
|
||||
private DiscoveryManagerImpl discoveryManager;
|
||||
|
||||
private Context context;
|
||||
private CastOptions options;
|
||||
private IMediaRouter router;
|
||||
private Map<String, ISessionProvider> sessionProviders = new HashMap<String, ISessionProvider>();
|
||||
public ISessionProvider defaultSessionProvider;
|
||||
|
||||
private MediaRouteSelector mergedSelector;
|
||||
|
||||
public CastContextImpl(IObjectWrapper context, CastOptions options, IMediaRouter router, Map<String, IBinder> sessionProviders) throws RemoteException {
|
||||
this.context = (Context) ObjectWrapper.unwrap(context);
|
||||
this.options = options;
|
||||
this.router = router;
|
||||
for (Map.Entry<String, IBinder> entry : sessionProviders.entrySet()) {
|
||||
this.sessionProviders.put(entry.getKey(), ISessionProvider.Stub.asInterface(entry.getValue()));
|
||||
}
|
||||
|
||||
String receiverApplicationId = options.getReceiverApplicationId();
|
||||
String defaultCategory = CastMediaControlIntent.categoryForCast(receiverApplicationId);
|
||||
|
||||
this.defaultSessionProvider = this.sessionProviders.get(defaultCategory);
|
||||
|
||||
// TODO: This should incorporate passed options
|
||||
this.mergedSelector = new MediaRouteSelector.Builder()
|
||||
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
|
||||
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
|
||||
.addControlCategory(defaultCategory)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getMergedSelectorAsBundle() throws RemoteException {
|
||||
return this.mergedSelector.asBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisibilityChangeListener(IAppVisibilityListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: addVisibilityChangeListener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVisibilityChangeListener(IAppVisibilityListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: removeVisibilityChangeListener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicationVisible() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: isApplicationVisible");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionManagerImpl getSessionManagerImpl() {
|
||||
if (this.sessionManager == null) {
|
||||
this.sessionManager = new SessionManagerImpl(this);
|
||||
}
|
||||
return this.sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDiscoveryManager getDiscoveryManagerImpl() throws RemoteException {
|
||||
if (this.discoveryManager == null) {
|
||||
this.discoveryManager = new DiscoveryManagerImpl(this);
|
||||
}
|
||||
return this.discoveryManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: destroy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(IObjectWrapper activity) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onActivityResumed");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(IObjectWrapper activity) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onActivityPaused");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReceiverApplicationId(String receiverApplicationId, Map sessionProvidersByCategory) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setReceiverApplicationId");
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
public IMediaRouter getRouter() {
|
||||
return this.router;
|
||||
}
|
||||
|
||||
public MediaRouteSelector getMergedSelector() {
|
||||
return this.mergedSelector;
|
||||
}
|
||||
|
||||
public CastOptions getOptions() {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedThis() throws RemoteException {
|
||||
return ObjectWrapper.wrap(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.ICastConnectionController;
|
||||
import com.google.android.gms.cast.framework.ICastContext;
|
||||
import com.google.android.gms.cast.framework.ICastSession;
|
||||
import com.google.android.gms.cast.framework.IReconnectionService;
|
||||
import com.google.android.gms.cast.framework.ISession;
|
||||
import com.google.android.gms.cast.framework.ISessionProxy;
|
||||
import com.google.android.gms.cast.framework.media.CastMediaOptions;
|
||||
import com.google.android.gms.cast.framework.internal.CastContextImpl;
|
||||
import com.google.android.gms.cast.framework.internal.CastSessionImpl;
|
||||
import com.google.android.gms.cast.framework.internal.MediaRouterCallbackImpl;
|
||||
import com.google.android.gms.cast.framework.internal.SessionImpl;
|
||||
import com.google.android.gms.cast.framework.media.IMediaNotificationService;
|
||||
import com.google.android.gms.cast.framework.media.internal.IFetchBitmapTask;
|
||||
import com.google.android.gms.cast.framework.media.internal.IFetchBitmapTaskProgressPublisher;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CastDynamiteModuleImpl extends ICastDynamiteModule.Stub {
|
||||
private static final String TAG = CastDynamiteModuleImpl.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public ICastContext newCastContextImpl(IObjectWrapper context, CastOptions options, IMediaRouter router, Map sessionProviders) throws RemoteException {
|
||||
return new CastContextImpl(context, options, router, sessionProviders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISession newSessionImpl(String category, String sessionId, ISessionProxy proxy) throws RemoteException {
|
||||
return new SessionImpl(category, sessionId, proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICastSession newCastSessionImpl(CastOptions options, IObjectWrapper session, ICastConnectionController controller) throws RemoteException {
|
||||
return new CastSessionImpl(options, session, controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMediaNotificationService newMediaNotificationServiceImpl(IObjectWrapper service, IObjectWrapper castContext, IObjectWrapper resources, CastMediaOptions options) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: newMediaNotificationServiceImpl");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IReconnectionService newReconnectionServiceImpl(IObjectWrapper service, IObjectWrapper sessionManager, IObjectWrapper discoveryManager) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: newReconnectionServiceImpl");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFetchBitmapTask newFetchBitmapTaskImpl(IObjectWrapper asyncTask, IFetchBitmapTaskProgressPublisher progressPublisher, int i1, int i2, boolean b1, long l1, int i3, int i4, int i5) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: newFetchBitmapTaskImpl");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import com.google.android.gms.cast.framework.ICastSession;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.ApplicationMetadata;
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.ICastConnectionController;
|
||||
import com.google.android.gms.common.api.Status;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
public class CastSessionImpl extends ICastSession.Stub {
|
||||
private static final String TAG = CastSessionImpl.class.getSimpleName();
|
||||
private CastOptions options;
|
||||
private SessionImpl session;
|
||||
private ICastConnectionController controller;
|
||||
|
||||
public CastSessionImpl(CastOptions options, IObjectWrapper session, ICastConnectionController controller) throws RemoteException {
|
||||
this.options = options;
|
||||
this.session = (SessionImpl) ObjectWrapper.unwrap(session);
|
||||
this.controller = controller;
|
||||
|
||||
this.session.setCastSession(this);
|
||||
}
|
||||
|
||||
public void launchApplication() throws RemoteException {
|
||||
this.controller.launchApplication(this.options.getReceiverApplicationId(), this.options.getLaunchOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle routeInfoExtra) throws RemoteException {
|
||||
this.controller.launchApplication(this.options.getReceiverApplicationId(), this.options.getLaunchOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int reason) {
|
||||
Log.d(TAG, "unimplemented Method: onConnectionSuspended");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(Status status) {
|
||||
Log.d(TAG, "unimplemented Method: onConnectionFailed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationConnectionSuccess(ApplicationMetadata applicationMetadata, String applicationStatus, String sessionId, boolean wasLaunched) {
|
||||
this.session.onApplicationConnectionSuccess(applicationMetadata, applicationStatus, sessionId, wasLaunched);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationConnectionFailure(int statusCode) {
|
||||
this.session.onApplicationConnectionFailure(statusCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnectFromDevice(boolean boolean1, int int1) {
|
||||
Log.d(TAG, "unimplemented Method: disconnectFromDevice");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManager;
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManagerListener;
|
||||
import com.google.android.gms.cast.framework.internal.CastContextImpl;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class DiscoveryManagerImpl extends IDiscoveryManager.Stub {
|
||||
private static final String TAG = DiscoveryManagerImpl.class.getSimpleName();
|
||||
|
||||
private CastContextImpl castContextImpl;
|
||||
|
||||
private Set discoveryManagerListeners = new HashSet();
|
||||
|
||||
public DiscoveryManagerImpl(CastContextImpl castContextImpl) {
|
||||
this.castContextImpl = castContextImpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDiscovery() {
|
||||
Log.d(TAG, "unimplemented Method: startDiscovery");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopDiscovery() {
|
||||
Log.d(TAG, "unimplemented Method: stopDiscovery");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDiscoveryManagerListener(IDiscoveryManagerListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: addDiscoveryManagerListener");
|
||||
this.discoveryManagerListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDiscoveryManagerListener(IDiscoveryManagerListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: removeDiscoveryManagerListener");
|
||||
this.discoveryManagerListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedThis() throws RemoteException {
|
||||
return ObjectWrapper.wrap(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.CastDevice;
|
||||
import com.google.android.gms.cast.framework.ISession;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
public class MediaRouterCallbackImpl extends IMediaRouterCallback.Stub {
|
||||
private static final String TAG = MediaRouterCallbackImpl.class.getSimpleName();
|
||||
|
||||
private CastContextImpl castContext;
|
||||
|
||||
public MediaRouterCallbackImpl(CastContextImpl castContext) {
|
||||
this.castContext = castContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteAdded(String routeId, Bundle extras) {
|
||||
Log.d(TAG, "unimplemented Method: onRouteAdded");
|
||||
}
|
||||
@Override
|
||||
public void onRouteChanged(String routeId, Bundle extras) {
|
||||
Log.d(TAG, "unimplemented Method: onRouteChanged");
|
||||
}
|
||||
@Override
|
||||
public void onRouteRemoved(String routeId, Bundle extras) {
|
||||
Log.d(TAG, "unimplemented Method: onRouteRemoved");
|
||||
}
|
||||
@Override
|
||||
public void onRouteSelected(String routeId, Bundle extras) throws RemoteException {
|
||||
CastDevice castDevice = CastDevice.getFromBundle(extras);
|
||||
|
||||
SessionImpl session = (SessionImpl) ObjectWrapper.unwrap(this.castContext.defaultSessionProvider.getSession(null));
|
||||
Bundle routeInfoExtras = this.castContext.getRouter().getRouteInfoExtrasById(routeId);
|
||||
if (routeInfoExtras != null) {
|
||||
session.start(this.castContext, castDevice, routeId, routeInfoExtras);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void unknown(String routeId, Bundle extras) {
|
||||
Log.d(TAG, "unimplemented Method: unknown");
|
||||
}
|
||||
@Override
|
||||
public void onRouteUnselected(String routeId, Bundle extras, int reason) {
|
||||
Log.d(TAG, "unimplemented Method: onRouteUnselected");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import com.google.android.gms.cast.ApplicationMetadata;
|
||||
import com.google.android.gms.cast.CastDevice;
|
||||
import com.google.android.gms.cast.framework.ISession;
|
||||
import com.google.android.gms.cast.framework.ISessionProxy;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
public class SessionImpl extends ISession.Stub {
|
||||
private static final String TAG = SessionImpl.class.getSimpleName();
|
||||
|
||||
private String category;
|
||||
private String sessionId;
|
||||
private ISessionProxy proxy;
|
||||
|
||||
private CastSessionImpl castSession;
|
||||
|
||||
private CastContextImpl castContext;
|
||||
private CastDevice castDevice;
|
||||
private Bundle routeInfoExtra;
|
||||
|
||||
private boolean mIsConnecting = false;
|
||||
private boolean mIsConnected = false;
|
||||
private String routeId = null;
|
||||
|
||||
public SessionImpl(String category, String sessionId, ISessionProxy proxy) {
|
||||
this.category = category;
|
||||
this.sessionId = sessionId;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public void start(CastContextImpl castContext, CastDevice castDevice, String routeId, Bundle routeInfoExtra) throws RemoteException {
|
||||
this.castContext = castContext;
|
||||
this.castDevice = castDevice;
|
||||
this.routeInfoExtra = routeInfoExtra;
|
||||
this.routeId = routeId;
|
||||
|
||||
this.mIsConnecting = true;
|
||||
this.mIsConnected = false;
|
||||
this.castContext.getSessionManagerImpl().onSessionStarting(this);
|
||||
this.proxy.start(routeInfoExtra);
|
||||
}
|
||||
|
||||
public void onApplicationConnectionSuccess(ApplicationMetadata applicationMetadata, String applicationStatus, String sessionId, boolean wasLaunched) {
|
||||
this.mIsConnecting = false;
|
||||
this.mIsConnected = true;
|
||||
this.castContext.getSessionManagerImpl().onSessionStarted(this, sessionId);
|
||||
try {
|
||||
this.castContext.getRouter().selectRouteById(this.getRouteId());
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Error calling selectRouteById: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void onApplicationConnectionFailure(int statusCode) {
|
||||
this.mIsConnecting = false;
|
||||
this.mIsConnected = false;
|
||||
this.routeId = null;
|
||||
this.castContext = null;
|
||||
this.castDevice = null;
|
||||
this.routeInfoExtra = null;
|
||||
this.castContext.getSessionManagerImpl().onSessionStartFailed(this, statusCode);
|
||||
try {
|
||||
this.castContext.getRouter().selectDefaultRoute();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Error calling selectDefaultRoute: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void onRouteSelected(Bundle extras) {
|
||||
}
|
||||
|
||||
public CastSessionImpl getCastSession() {
|
||||
return this.castSession;
|
||||
}
|
||||
|
||||
public void setCastSession(CastSessionImpl castSession) {
|
||||
this.castSession = castSession;
|
||||
}
|
||||
|
||||
public ISessionProxy getSessionProxy() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
public IObjectWrapper getWrappedSession() throws RemoteException {
|
||||
if (this.proxy == null) {
|
||||
return ObjectWrapper.wrap(null);
|
||||
}
|
||||
return this.proxy.getWrappedSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return this.category;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionId() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRouteId() {
|
||||
return this.routeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return this.mIsConnected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnecting() {
|
||||
return this.mIsConnecting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisconnecting() {
|
||||
Log.d(TAG, "unimplemented Method: isDisconnecting");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisconnected() {
|
||||
Log.d(TAG, "unimplemented Method: isDisconnected");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResuming() {
|
||||
Log.d(TAG, "unimplemented Method: isResuming");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuspended() {
|
||||
Log.d(TAG, "unimplemented Method: isSuspended");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySessionStarted(String sessionId) {
|
||||
Log.d(TAG, "unimplemented Method: notifySessionStarted");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyFailedToStartSession(int error) {
|
||||
Log.d(TAG, "unimplemented Method: notifyFailedToStartSession");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySessionEnded(int error) {
|
||||
Log.d(TAG, "unimplemented Method: notifySessionEnded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySessionResumed(boolean wasSuspended) {
|
||||
Log.d(TAG, "unimplemented Method: notifySessionResumed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyFailedToResumeSession(int error) {
|
||||
Log.d(TAG, "unimplemented Method: notifyFailedToResumeSession");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySessionSuspended(int reason) {
|
||||
Log.d(TAG, "unimplemented Method: notifySessionSuspended");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedObject() {
|
||||
return ObjectWrapper.wrap(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.cast.framework.CastState;
|
||||
import com.google.android.gms.cast.framework.ICastStateListener;
|
||||
import com.google.android.gms.cast.framework.ISession;
|
||||
import com.google.android.gms.cast.framework.ISessionManager;
|
||||
import com.google.android.gms.cast.framework.ISessionManagerListener;
|
||||
import com.google.android.gms.cast.framework.internal.CastContextImpl;
|
||||
import com.google.android.gms.cast.framework.internal.SessionImpl;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SessionManagerImpl extends ISessionManager.Stub {
|
||||
private static final String TAG = SessionManagerImpl.class.getSimpleName();
|
||||
|
||||
private CastContextImpl castContext;
|
||||
|
||||
private Set<ISessionManagerListener> sessionManagerListeners = new HashSet<ISessionManagerListener>();
|
||||
private Set<ICastStateListener> castStateListeners = new HashSet<ICastStateListener>();
|
||||
|
||||
private Map<String, SessionImpl> routeSessions = new HashMap<String, SessionImpl>();
|
||||
|
||||
private SessionImpl currentSession;
|
||||
|
||||
private int castState = CastState.NO_DEVICES_AVAILABLE;
|
||||
|
||||
public SessionManagerImpl(CastContextImpl castContext) {
|
||||
this.castContext = castContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedCurrentSession() throws RemoteException {
|
||||
if (this.currentSession == null) {
|
||||
return ObjectWrapper.wrap(null);
|
||||
}
|
||||
return this.currentSession.getWrappedSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endCurrentSession(boolean b, boolean stopCasting) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: endCurrentSession");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSessionManagerListener(ISessionManagerListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: addSessionManagerListener");
|
||||
this.sessionManagerListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSessionManagerListener(ISessionManagerListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: removeSessionManagerListener");
|
||||
this.sessionManagerListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCastStateListener(ICastStateListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: addCastStateListener");
|
||||
this.castStateListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCastStateListener(ICastStateListener listener) {
|
||||
Log.d(TAG, "unimplemented Method: removeCastStateListener");
|
||||
this.castStateListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedThis() throws RemoteException {
|
||||
return ObjectWrapper.wrap(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCastState() {
|
||||
return this.castState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startSession(Bundle params) {
|
||||
Log.d(TAG, "unimplemented Method: startSession");
|
||||
String routeId = params.getString("CAST_INTENT_TO_CAST_ROUTE_ID_KEY");
|
||||
String sessionId = params.getString("CAST_INTENT_TO_CAST_SESSION_ID_KEY");
|
||||
}
|
||||
|
||||
public void onRouteSelected(String routeId, Bundle extras) {
|
||||
Log.d(TAG, "unimplemented Method: onRouteSelected: " + routeId);
|
||||
}
|
||||
|
||||
private void setCastState(int castState) {
|
||||
this.castState = castState;
|
||||
this.onCastStateChanged();
|
||||
}
|
||||
|
||||
public void onCastStateChanged() {
|
||||
for (ICastStateListener listener : this.castStateListeners) {
|
||||
try {
|
||||
listener.onCastStateChanged(this.castState);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onCastStateChanged: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionStarting(SessionImpl session) {
|
||||
this.setCastState(CastState.CONNECTING);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionStarting(session.getSessionProxy().getWrappedSession());
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionStarting: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionStartFailed(SessionImpl session, int error) {
|
||||
this.currentSession = null;
|
||||
this.setCastState(CastState.NOT_CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionStartFailed(session.getSessionProxy().getWrappedSession(), error);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionStartFailed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionStarted(SessionImpl session, String sessionId) {
|
||||
this.currentSession = session;
|
||||
this.setCastState(CastState.CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionStarted(session.getSessionProxy().getWrappedSession(), sessionId);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionStarted: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionResumed(SessionImpl session, boolean wasSuspended) {
|
||||
this.setCastState(CastState.CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionResumed(session.getSessionProxy().getWrappedSession(), wasSuspended);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionResumed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionEnding(SessionImpl session) {
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionEnding(session.getSessionProxy().getWrappedSession());
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionEnding: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionEnded(SessionImpl session, int error) {
|
||||
this.currentSession = null;
|
||||
this.setCastState(CastState.NOT_CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionEnded(session.getSessionProxy().getWrappedSession(), error);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionEnded: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionResuming(SessionImpl session, String sessionId) {
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionResuming(session.getSessionProxy().getWrappedSession(), sessionId);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionResuming: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionResumeFailed(SessionImpl session, int error) {
|
||||
this.currentSession = null;
|
||||
this.setCastState(CastState.NOT_CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionResumeFailed(session.getSessionProxy().getWrappedSession(), error);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionResumeFailed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSessionSuspended(SessionImpl session, int reason) {
|
||||
this.setCastState(CastState.NOT_CONNECTED);
|
||||
for (ISessionManagerListener listener : this.sessionManagerListeners) {
|
||||
try {
|
||||
listener.onSessionSuspended(session.getSessionProxy().getWrappedSession(), reason);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Remote exception calling onSessionSuspended: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
play-services-cast-framework/src/main/AndroidManifest.xml
Normal file
30
play-services-cast-framework/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2017 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
|
||||
<queries>
|
||||
<package android:name="com.google.android.gms.policy_cast_dynamite"/>
|
||||
</queries>
|
||||
|
||||
<application>
|
||||
<receiver
|
||||
android:name="com.google.android.gms.cast.framework.media.MediaIntentReceiver"
|
||||
android:exported="false"/>
|
||||
|
||||
<service
|
||||
android:name="com.google.android.gms.cast.framework.media.MediaNotificationService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="mediaPlayback"/>
|
||||
|
||||
<service
|
||||
android:name="com.google.android.gms.cast.framework.ReconnectionService"
|
||||
android:exported="false"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
parcelable CastOptions;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IAppVisibilityListener {
|
||||
IObjectWrapper getThisObject() = 0;
|
||||
void onAppEnteredForeground() = 1;
|
||||
void onAppEnteredBackground() = 2;
|
||||
int getSupportedVersion() = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.cast.LaunchOptions;
|
||||
|
||||
interface ICastConnectionController {
|
||||
void joinApplication(String applicationId, String sessionId) = 0;
|
||||
void launchApplication(String applicationId, in LaunchOptions launchOptions) = 1;
|
||||
void stopApplication(String sessionId) = 2;
|
||||
void closeConnection(int reason) = 3; // Maybe?
|
||||
int getSupportedVersion() = 4;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.cast.framework.IAppVisibilityListener;
|
||||
import com.google.android.gms.cast.framework.ISessionManager;
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManager;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ICastContext {
|
||||
Bundle getMergedSelectorAsBundle() = 0;
|
||||
boolean isApplicationVisible() = 1;
|
||||
void addVisibilityChangeListener(IAppVisibilityListener listener) = 2;
|
||||
void removeVisibilityChangeListener(IAppVisibilityListener listener) = 3;
|
||||
ISessionManager getSessionManagerImpl() = 4;
|
||||
IDiscoveryManager getDiscoveryManagerImpl() = 5;
|
||||
void destroy() = 6; // deprecated?
|
||||
void onActivityResumed(in IObjectWrapper activity) = 7; // deprecated?
|
||||
void onActivityPaused(in IObjectWrapper activity) = 8; // deprecated?
|
||||
IObjectWrapper getWrappedThis() = 9;
|
||||
void setReceiverApplicationId(String receiverApplicationId, in Map/*<String, IBinder>*/ sessionProvidersByCategory) = 10;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.gms.cast.ApplicationMetadata;
|
||||
import com.google.android.gms.common.api.Status;
|
||||
|
||||
interface ICastSession {
|
||||
void onConnected(in Bundle routeInfoExtra) = 0;
|
||||
void onConnectionSuspended(int reason) = 1;
|
||||
void onConnectionFailed(in Status status) = 2;
|
||||
void onApplicationConnectionSuccess(in ApplicationMetadata applicationMetadata, String applicationStatus, String sessionId, boolean wasLaunched) = 3;
|
||||
void onApplicationConnectionFailure(int statusCode) = 4;
|
||||
void disconnectFromDevice(boolean boolean1, int int1) = 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ICastStateListener {
|
||||
IObjectWrapper getWrappedThis() = 0;
|
||||
void onCastStateChanged(int newState) = 1;
|
||||
int getSupportedVersion() = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManagerListener;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IDiscoveryManager {
|
||||
void startDiscovery() = 0; // Maybe?
|
||||
void stopDiscovery() = 1; // Maybe?
|
||||
void addDiscoveryManagerListener(IDiscoveryManagerListener listener) = 2;
|
||||
void removeDiscoveryManagerListener(IDiscoveryManagerListener listener) = 3;
|
||||
IObjectWrapper getWrappedThis() = 4;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IDiscoveryManagerListener {
|
||||
IObjectWrapper getWrappedThis() = 0;
|
||||
void onDeviceAvailabilityChanged(boolean deviceAvailable) = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
interface IReconnectionService {
|
||||
void onCreate() = 0;
|
||||
int onStartCommand(in Intent intent, int flags, int startId) = 1;
|
||||
IBinder onBind(in Intent intent) = 2;
|
||||
void onDestroy() = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ISession {
|
||||
IObjectWrapper getWrappedObject() = 0;
|
||||
String getCategory() = 1;
|
||||
String getSessionId() = 2;
|
||||
String getRouteId() = 3;
|
||||
boolean isConnected() = 4;
|
||||
boolean isConnecting() = 5;
|
||||
boolean isDisconnecting() = 6;
|
||||
boolean isDisconnected() = 7;
|
||||
boolean isResuming() = 8;
|
||||
boolean isSuspended() = 9;
|
||||
void notifySessionStarted(String sessionId) = 10;
|
||||
void notifyFailedToStartSession(int error) = 11;
|
||||
void notifySessionEnded(int error) = 12;
|
||||
void notifySessionResumed(boolean wasSuspended) = 13;
|
||||
void notifyFailedToResumeSession(int error) = 14;
|
||||
void notifySessionSuspended(int reason) = 15;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.cast.framework.ISessionManagerListener;
|
||||
import com.google.android.gms.cast.framework.ICastStateListener;
|
||||
|
||||
interface ISessionManager {
|
||||
IObjectWrapper getWrappedCurrentSession() = 0;
|
||||
void addSessionManagerListener(ISessionManagerListener listener) = 1;
|
||||
void removeSessionManagerListener(ISessionManagerListener listener) = 2;
|
||||
void addCastStateListener(ICastStateListener listener) = 3;
|
||||
void removeCastStateListener(ICastStateListener listener) = 4;
|
||||
void endCurrentSession(boolean b, boolean stopCasting) = 5;
|
||||
IObjectWrapper getWrappedThis() = 6;
|
||||
int getCastState() = 7;
|
||||
void startSession(in Bundle options) = 8;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ISessionManagerListener {
|
||||
IObjectWrapper getWrappedThis() = 0;
|
||||
void onSessionStarting(IObjectWrapper session) = 1;
|
||||
void onSessionStarted(IObjectWrapper session, String sessionId) = 2;
|
||||
void onSessionStartFailed(IObjectWrapper session, int error) = 3;
|
||||
void onSessionEnding(IObjectWrapper session) = 4;
|
||||
void onSessionEnded(IObjectWrapper session, int error) = 5;
|
||||
void onSessionResuming(IObjectWrapper session, String sessionId) = 6;
|
||||
void onSessionResumed(IObjectWrapper session, boolean wasSuspended) = 7;
|
||||
void onSessionResumeFailed(IObjectWrapper session, int error) = 8;
|
||||
void onSessionSuspended(IObjectWrapper session, int reason) = 9;
|
||||
int getSupportedVersion() = 10;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ISessionProvider {
|
||||
IObjectWrapper getSession(String sessionId) = 0;
|
||||
boolean isSessionRecoverable() = 1;
|
||||
String getCategory() = 2;
|
||||
int getSupportedVersion() = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ISessionProxy {
|
||||
IObjectWrapper getWrappedSession() = 0;
|
||||
void start(in Bundle extras) = 1;
|
||||
void resume(in Bundle extras) = 2;
|
||||
void end(boolean paramBoolean) = 3;
|
||||
long getSessionRemainingTimeMs() = 4;
|
||||
int getSupportedVersion() = 5;
|
||||
void onStarting(in Bundle routeInfoExtra) = 6;
|
||||
void onResuming(in Bundle routeInfoExtra) = 7;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.ICastConnectionController;
|
||||
import com.google.android.gms.cast.framework.ICastContext;
|
||||
import com.google.android.gms.cast.framework.ICastSession;
|
||||
import com.google.android.gms.cast.framework.IReconnectionService;
|
||||
import com.google.android.gms.cast.framework.ISession;
|
||||
import com.google.android.gms.cast.framework.ISessionProxy;
|
||||
import com.google.android.gms.cast.framework.internal.IMediaRouter;
|
||||
import com.google.android.gms.cast.framework.media.CastMediaOptions;
|
||||
import com.google.android.gms.cast.framework.media.IMediaNotificationService;
|
||||
import com.google.android.gms.cast.framework.media.internal.IFetchBitmapTask;
|
||||
import com.google.android.gms.cast.framework.media.internal.IFetchBitmapTaskProgressPublisher;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ICastDynamiteModule {
|
||||
ICastContext newCastContextImpl(in IObjectWrapper context, in CastOptions options, IMediaRouter router, in Map sessionProviders) = 0;
|
||||
ISession newSessionImpl(String category, String sessionId, ISessionProxy proxy) = 1;
|
||||
ICastSession newCastSessionImpl(in CastOptions options, in IObjectWrapper session, ICastConnectionController controller) = 2;
|
||||
IMediaNotificationService newMediaNotificationServiceImpl(in IObjectWrapper service, in IObjectWrapper castContext, in IObjectWrapper resources, in CastMediaOptions options) = 3;
|
||||
IReconnectionService newReconnectionServiceImpl(in IObjectWrapper service, in IObjectWrapper sessionManager, in IObjectWrapper discoveryManager) = 4;
|
||||
IFetchBitmapTask newFetchBitmapTaskImpl(in IObjectWrapper asyncTask, IFetchBitmapTaskProgressPublisher progressPublisher, int i1, int i2, boolean b1, long l1, int i3, int i4, int i5) = 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.gms.cast.framework.internal.IMediaRouterCallback;
|
||||
|
||||
interface IMediaRouter {
|
||||
void registerMediaRouterCallbackImpl(in Bundle selector, IMediaRouterCallback callback) = 0;
|
||||
void addCallback(in Bundle selector, int flags) = 1;
|
||||
void removeCallback(in Bundle selector) = 2;
|
||||
boolean isRouteAvailable(in Bundle selector, int flags) = 3;
|
||||
void selectRouteById(String routeId) = 4;
|
||||
void selectDefaultRoute() = 5;
|
||||
boolean isDefaultRouteSelected() = 6; // Maybe?
|
||||
Bundle getRouteInfoExtrasById(String routeId) = 7;
|
||||
String getSelectedRouteId() = 8; // Maybe?
|
||||
int getSupportedVersion() = 9;
|
||||
void clearCallbacks() = 10;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.google.android.gms.cast.framework.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
interface IMediaRouterCallback {
|
||||
void onRouteAdded(String routeId, in Bundle extras) = 0;
|
||||
void onRouteChanged(String routeId, in Bundle extras) = 1;
|
||||
void onRouteRemoved(String routeId, in Bundle extras) = 2;
|
||||
void onRouteSelected(String routeId, in Bundle extras) = 3;
|
||||
void unknown(String routeId, in Bundle extras) = 4;
|
||||
void onRouteUnselected(String routeId, in Bundle extras, int reason) = 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
parcelable CastMediaOptions;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
import com.google.android.gms.common.images.WebImage;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IImagePicker {
|
||||
// WebImage onPickImage(MediaMetadata metadata, int int1) = 0;
|
||||
IObjectWrapper getWrappedClientObject() = 1;
|
||||
int unknown1() = 2;
|
||||
// WebImage onPickImage(MediaMetadata metadata, ImageHints imageHints) = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
interface IMediaNotificationService {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
interface INotificationActionsProvider {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
parcelable NotificationOptions;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.cast.framework.media.internal;
|
||||
|
||||
interface IFetchBitmapTask {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.cast.framework.media.internal;
|
||||
|
||||
interface IFetchBitmapTaskProgressPublisher {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
public class CastButtonFactory {
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.gms.cast.framework.internal.IMediaRouter;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.gms.tasks.Tasks;
|
||||
import org.microg.gms.cast.CastDynamiteModule;
|
||||
import org.microg.gms.cast.CastSessionProvider;
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class CastContext {
|
||||
/**
|
||||
* The metadata key to specify the fully qualified name of the {@link OptionsProvider} implementation in the
|
||||
* {@code AndroidManifest.xml}.
|
||||
*/
|
||||
public static final String OPTIONS_PROVIDER_CLASS_NAME_KEY = "com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME";
|
||||
|
||||
/**
|
||||
* Returns the shared instance of {@link CastContext}. This method must be called after {@link CastContext} is initialized through
|
||||
* {@link #getSharedInstance(Context, Executor)}. Otherwise, this method will return {@code null}.
|
||||
*
|
||||
* @throws IllegalStateException If this method is not called on the main thread.
|
||||
*/
|
||||
public static CastContext getSharedInstance() {
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shared instance of {@link CastContext}. The shared instance will be initialized on the first time this method is called.
|
||||
*
|
||||
* @param context An application {@link Context}. If this is not an application {@link Context}, {@link Context#getApplicationContext()} will be called on
|
||||
* the given context, to retrieve it.
|
||||
* @throws IllegalStateException If any of the following:
|
||||
* <ul>
|
||||
* <li>This method is not called on the main thread.</li>
|
||||
* <li>
|
||||
* The fully qualified name of the {@link OptionsProvider} implementation is not specified as a metadata in the
|
||||
* {@code AndroidManifest.xml} with key {@link #OPTIONS_PROVIDER_CLASS_NAME_KEY}.
|
||||
* </li>
|
||||
* <li>{@code optionsProviderClass} or its nullary constructor is not accessible.</li>
|
||||
* <li>Instantiation of {@link OptionsProvider} fails for some other reason.</li>
|
||||
* </ul>
|
||||
* @deprecated Use {@link #getSharedInstance(Context, Executor)} instead to handle the exception when Cast SDK fails to load the internal
|
||||
* Cast module.
|
||||
*/
|
||||
@Deprecated
|
||||
public static CastContext getSharedInstance(Context context) {
|
||||
if (sharedInstance == null) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
OptionsProvider optionsProvider = getOptionsProvider(appContext);
|
||||
CastOptions castOptions = optionsProvider.getCastOptions(appContext);
|
||||
try {
|
||||
sharedInstance = new CastContext(appContext, castOptions, optionsProvider.getAdditionalSessionProviders(appContext));
|
||||
} catch (ModuleUnavailableException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an asynchronous Task API call on the shared instance of {@link CastContext}. The shared instance will be initialized
|
||||
* on the first time this method is called.
|
||||
* <p>
|
||||
* Note that {@link #getSharedInstance(Context, Executor)} should be called in the {@link Activity#onCreate(Bundle)} method
|
||||
* of the activities that might display a Cast button. The Cast SDK provides {@link CastButtonFactory} to set up a Cast button.
|
||||
* <p>
|
||||
* Note that {@link ModuleUnavailableException} could be thrown when the SDK fails to load the internal Cast module. The
|
||||
* caller will get the exception from {@link Task#getException()} when the task completes.
|
||||
*
|
||||
* @param context An application {@link Context}. If this is not an application {@link Context}, {@link Context#getApplicationContext()} will be called on
|
||||
* the given context, to retrieve it.
|
||||
* @param executor An {@link Executor} to load the internal Cast module.
|
||||
* @throws IllegalStateException If any of the following:
|
||||
* <ul>
|
||||
* <li>This method is not called on the main thread.</li>
|
||||
* <li>
|
||||
* The fully qualified name of the {@link OptionsProvider} implementation is not specified as a metadata in the
|
||||
* {@code AndroidManifest.xml} with key {@link #OPTIONS_PROVIDER_CLASS_NAME_KEY}.
|
||||
* </li>
|
||||
* <li>{@code optionsProviderClass} or its nullary constructor is not accessible.</li>
|
||||
* <li>Instantiation of {@link OptionsProvider} fails for some other reason.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static Task<CastContext> getSharedInstance(Context context, Executor executor) {
|
||||
if (sharedInstance != null) {
|
||||
return Tasks.forResult(sharedInstance);
|
||||
}
|
||||
Context appContext = context.getApplicationContext();
|
||||
OptionsProvider optionsProvider = getOptionsProvider(appContext);
|
||||
CastOptions castOptions = optionsProvider.getCastOptions(appContext);
|
||||
return Tasks.call(executor, () -> {
|
||||
sharedInstance = new CastContext(appContext, castOptions, optionsProvider.getAdditionalSessionProviders(appContext));
|
||||
return sharedInstance;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link SessionManager}, never returns {@code null}.
|
||||
*
|
||||
* @throws IllegalStateException If this method is not called on the main thread.
|
||||
*/
|
||||
@NonNull
|
||||
public SessionManager getSessionManager() {
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
private static volatile CastContext sharedInstance;
|
||||
private Context appContext;
|
||||
private CastOptions castOptions;
|
||||
private IMediaRouter mediaRouter;
|
||||
private List<SessionProvider> additionalSessionProviders;
|
||||
private CastSessionProvider castSessionProvider;
|
||||
private ICastContext delegate;
|
||||
private SessionManager sessionManager;
|
||||
private DiscoveryManager discoveryManager;
|
||||
|
||||
private CastContext(Context appContext, CastOptions castOptions, @Nullable List<SessionProvider> additionalSessionProviders) throws ModuleUnavailableException {
|
||||
this.appContext = appContext;
|
||||
this.castOptions = castOptions;
|
||||
this.mediaRouter = null; // TODO
|
||||
this.additionalSessionProviders = additionalSessionProviders;
|
||||
this.castSessionProvider = new CastSessionProvider(appContext, castOptions);
|
||||
try {
|
||||
this.delegate = CastDynamiteModule.newCastContext(appContext, castOptions, mediaRouter, getSessionProviderMap());
|
||||
this.sessionManager = new SessionManager(appContext, delegate.getSessionManagerImpl());
|
||||
this.discoveryManager = new DiscoveryManager(appContext, delegate.getDiscoveryManagerImpl());
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException("Failed to call dynamite module", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, IBinder> getSessionProviderMap() {
|
||||
Map<String, IBinder> map = new HashMap<>();
|
||||
if (castSessionProvider != null) {
|
||||
map.put(castSessionProvider.getCategory(), castSessionProvider.asBinder());
|
||||
}
|
||||
List<SessionProvider> list = this.additionalSessionProviders;
|
||||
if (list != null) {
|
||||
for (SessionProvider sessionProvider : list) {
|
||||
if (sessionProvider == null) throw new IllegalArgumentException("Additional SessionProvider must not be null.");
|
||||
if (sessionProvider.getCategory() == null || sessionProvider.getCategory().isEmpty())
|
||||
throw new IllegalArgumentException("Category for SessionProvider must not be null or empty string.");
|
||||
if (map.containsKey(sessionProvider.getCategory()))
|
||||
throw new IllegalArgumentException("SessionProvider for category " + sessionProvider.getCategory() + " already added");
|
||||
map.put(sessionProvider.getCategory(), sessionProvider.asBinder());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static OptionsProvider getOptionsProvider(Context context) {
|
||||
try {
|
||||
Bundle metaData = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA).metaData;
|
||||
String optionsProviderClassName = metaData.getString(OPTIONS_PROVIDER_CLASS_NAME_KEY);
|
||||
if (optionsProviderClassName != null) {
|
||||
return Class.forName(optionsProviderClassName).asSubclass(OptionsProvider.class).getDeclaredConstructor().newInstance();
|
||||
}
|
||||
throw new IllegalStateException("The fully qualified name of the implementation of OptionsProvider must be provided as a metadata in the AndroidManifest.xml with key com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME.");
|
||||
} catch (PackageManager.NameNotFoundException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException |
|
||||
InvocationTargetException | NullPointerException e) {
|
||||
throw new IllegalStateException("Failed to initialize CastContext.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
DiscoveryManager getDiscoveryManager() {
|
||||
return discoveryManager;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2016 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.microg.safeparcel.AutoSafeParcelable;
|
||||
import org.microg.safeparcel.SafeParceled;
|
||||
|
||||
import com.google.android.gms.cast.framework.media.CastMediaOptions;
|
||||
import com.google.android.gms.cast.LaunchOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Configuration parameters for initializing the {@link CastContext}. The {@link CastOptions.Builder} is used to create an instance of
|
||||
* {@link CastOptions}, and so contains the corresponding setter methods.
|
||||
*/
|
||||
public class CastOptions extends AutoSafeParcelable {
|
||||
@Field(1)
|
||||
private int versionCode = 1;
|
||||
@Field(2)
|
||||
private String receiverApplicationId;
|
||||
@Field(3)
|
||||
private ArrayList<String> supportedNamespaces;
|
||||
@Field(4)
|
||||
private boolean stopReceiverApplicationWhenEndingSession;
|
||||
@Field(5)
|
||||
private LaunchOptions launchOptions;
|
||||
@Field(6)
|
||||
private boolean resumeSavedSession;
|
||||
@Field(7)
|
||||
private CastMediaOptions castMediaOptions;
|
||||
@Field(8)
|
||||
private boolean enableReconnectionService;
|
||||
@Field(9)
|
||||
private double volumeDeltaBeforeIceCreamSandwich;
|
||||
@Field(10)
|
||||
private boolean enableIpv6Support;
|
||||
@Field(11)
|
||||
private boolean outputSwitcherEnabled;
|
||||
@Field(12)
|
||||
private boolean isRemoteToLocalEnabled;
|
||||
@Field(13)
|
||||
private List<String> routeDiscoveryReceiverApplicationIds;
|
||||
@Field(14)
|
||||
private boolean sessionTransferEnabled;
|
||||
@Field(15)
|
||||
private int persistCastButtonEnabled;
|
||||
@Field(16)
|
||||
private boolean resumeSessionAfterTransferEnabled;
|
||||
|
||||
/**
|
||||
* Returns the {@link CastMediaOptions} that is used to configure a media session.
|
||||
*/
|
||||
public CastMediaOptions getCastMediaOptions() {
|
||||
return castMediaOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@link ReconnectionService} should be enabled when needed to better handle session recovery.
|
||||
*/
|
||||
public boolean getEnableReconnectionService() {
|
||||
return enableReconnectionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link LaunchOptions}.
|
||||
*/
|
||||
public LaunchOptions getLaunchOptions() {
|
||||
return launchOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cast receiver application ID. This ID is used in discovering supported receivers, and launching an application
|
||||
* when starting a new session.
|
||||
*/
|
||||
public String getReceiverApplicationId() {
|
||||
return receiverApplicationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the saved session should be resumed if it was dropped unexpectedly. Returns {@code false} if the saved
|
||||
* session should not be resumed in this case.
|
||||
*/
|
||||
public boolean getResumeSavedSession() {
|
||||
return resumeSavedSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the receiver application should be stopped when the session is ended by the user. Returns {@code false} if the
|
||||
* receiver application should not be stopped in this case.
|
||||
*/
|
||||
public boolean getStopReceiverApplicationWhenEndingSession() {
|
||||
return stopReceiverApplicationWhenEndingSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported cast namespaces.
|
||||
*/
|
||||
@NonNull
|
||||
public List<String> getSupportedNamespaces() {
|
||||
return supportedNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of receiver device volume to increase or decrease when the physical volume key is pressed on an
|
||||
* Android device older than ICE CREAM SANDWICH. The SDK will call this method to obtain the volume delta when
|
||||
* {@link CastContext#onDispatchVolumeKeyEventBeforeJellyBean(KeyEvent)} is called. The return value is not used on
|
||||
* Android devices running ICE CREAM SANDWICH or newer.
|
||||
*/
|
||||
@Deprecated
|
||||
public double getVolumeDeltaBeforeIceCreamSandwich() {
|
||||
return volumeDeltaBeforeIceCreamSandwich;
|
||||
}
|
||||
|
||||
public static Creator<CastOptions> CREATOR = new AutoCreator<CastOptions>(CastOptions.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
public class CastSession extends Session{
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
public final class CastState {
|
||||
public static final int NO_DEVICES_AVAILABLE = 1;
|
||||
public static final int NOT_CONNECTED = 2;
|
||||
public static final int CONNECTING = 3;
|
||||
public static final int CONNECTED = 4;
|
||||
|
||||
public static String toString(int castState) {
|
||||
switch (castState) {
|
||||
case NO_DEVICES_AVAILABLE:
|
||||
return "NO_DEVICES_AVAILABLE";
|
||||
case NOT_CONNECTED:
|
||||
return "NOT_CONNECTED";
|
||||
case CONNECTING:
|
||||
return "CONNECTING";
|
||||
case CONNECTED:
|
||||
return "CONNECTED";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.cast.framework.IDiscoveryManager;
|
||||
import com.google.android.gms.cast.framework.ISessionManager;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
class DiscoveryManager {
|
||||
private Context context;
|
||||
private IDiscoveryManager delegate;
|
||||
|
||||
public DiscoveryManager(Context context, IDiscoveryManager delegate) {
|
||||
this.context = context;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public IObjectWrapper getWrappedThis() {
|
||||
try {
|
||||
return delegate.getWrappedThis();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
/**
|
||||
* An exception thrown when the internal Cast module fails to load.
|
||||
*/
|
||||
public class ModuleUnavailableException extends Exception {
|
||||
public ModuleUnavailableException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Developers should implement this interface to provide options needed to create and initialize {@link CastContext}. The
|
||||
* implementation class must have a constructor without argument. The SDK will call that constructor to instantiate a new
|
||||
* instance.
|
||||
*/
|
||||
public interface OptionsProvider {
|
||||
/**
|
||||
* Provides a list of custom {@link SessionProvider} instances for non-Cast devices. This is optional.
|
||||
*
|
||||
* @param appContext The application {@link Context}.
|
||||
* @return the list of {@link SessionProvider} instances, may be {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
List<SessionProvider> getAdditionalSessionProviders(@NonNull Context appContext);
|
||||
|
||||
/**
|
||||
* Provides {@link CastOptions}, which affects discovery and session management of a Cast device.
|
||||
*
|
||||
* @param appContext The application {@link Context}.
|
||||
* @return the {@link CastOptions}, must not be {@code null}.
|
||||
*/
|
||||
@NonNull
|
||||
CastOptions getCastOptions(@NonNull Context appContext);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.microg.gms.cast.CastDynamiteModule;
|
||||
|
||||
public class ReconnectionService extends Service {
|
||||
private IReconnectionService delegate;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
CastContext castContext = CastContext.getSharedInstance(this);
|
||||
delegate = CastDynamiteModule.newReconnectionService(this, castContext.getSessionManager().getWrappedThis(), castContext.getDiscoveryManager().getWrappedThis());
|
||||
if (delegate != null) {
|
||||
try {
|
||||
delegate.onCreate();
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (delegate != null) {
|
||||
try {
|
||||
delegate.onStartCommand(intent, flags, startId);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (delegate != null) {
|
||||
try {
|
||||
return delegate.onBind(intent);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (delegate != null) {
|
||||
try {
|
||||
delegate.onDestroy();
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
public class Session {
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
public class SessionManager {
|
||||
private Context context;
|
||||
private ISessionManager delegate;
|
||||
|
||||
SessionManager(Context context, ISessionManager delegate) {
|
||||
this.context = context;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the current session.
|
||||
*
|
||||
* @param stopCasting Should the receiver application be stopped when ending the current Session.
|
||||
* @throws IllegalStateException If this method is not called on the main thread.
|
||||
*/
|
||||
public void endCurrentSession(boolean stopCasting) {
|
||||
try {
|
||||
delegate.endCurrentSession(true, stopCasting);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current session if it is an instance of {@link CastSession}, otherwise returns {@code null}.
|
||||
*
|
||||
* @throws IllegalStateException If this method is not called on the main thread.
|
||||
*/
|
||||
public CastSession getCurrentCastSession() {
|
||||
Session currentSession = getCurrentSession();
|
||||
if (currentSession instanceof CastSession) {
|
||||
return (CastSession) currentSession;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active session. Returns {@code null} if no session is active.
|
||||
*
|
||||
* @throws IllegalStateException If this method is not called on the main thread.
|
||||
*/
|
||||
public Session getCurrentSession() {
|
||||
try {
|
||||
return ObjectWrapper.unwrapTyped(delegate.getWrappedCurrentSession(), Session.class);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
IObjectWrapper getWrappedThis() {
|
||||
try {
|
||||
return delegate.getWrappedThis();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import org.microg.gms.cast.ISessionProviderImpl;
|
||||
|
||||
/**
|
||||
* An abstract base class for performing session construction. The SDK uses a subclass of {@link SessionProvider} to
|
||||
* construct {@link CastSession} internally. If your app wants to support other types of {@link Session} then you should subclass this
|
||||
* class. Subclasses must implement {@link #createSession(String)} and {@link #isSessionRecoverable()}, which will be called by
|
||||
* the Cast SDK during the lifecycle of the session. All methods must be called from the main thread.
|
||||
*/
|
||||
public abstract class SessionProvider {
|
||||
private Context context;
|
||||
private String category;
|
||||
private ISessionProvider bindable = new ISessionProviderImpl(this);
|
||||
|
||||
/**
|
||||
* Constructs a {@link SessionProvider} with a category string. The category uniquely identifies a {@link Session} created by this
|
||||
* provider.
|
||||
*
|
||||
* @param applicationContext The application Context of the calling app.
|
||||
* @param category The category string used to create {@link Session}.
|
||||
*/
|
||||
protected SessionProvider(Context applicationContext, String category) {
|
||||
this.context = applicationContext;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Session}. This method is called by the SDK to create a new session.
|
||||
*/
|
||||
public abstract Session createSession(String sessionId);
|
||||
|
||||
/**
|
||||
* Returns the category string for this {@link SessionProvider}.
|
||||
*/
|
||||
public final String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application {@link Context} used to construct this instance.
|
||||
*/
|
||||
public final Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a previously constructed session can be resumed. Subclasses should check any persisted information
|
||||
* about the previous session, such as a session ID, and return true only if it is possible to resume that session. This
|
||||
* method is called by the SDK when it tries to resume a previously saved session.
|
||||
*/
|
||||
public abstract boolean isSessionRecoverable();
|
||||
|
||||
public IBinder asBinder() {
|
||||
return bindable.asBinder();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
import org.microg.safeparcel.AutoSafeParcelable;
|
||||
import org.microg.safeparcel.SafeParceled;
|
||||
|
||||
public class CastMediaOptions extends AutoSafeParcelable {
|
||||
|
||||
@Field(1)
|
||||
private int versionCode = 1;
|
||||
@Field(2)
|
||||
public String mediaIntentReceiverClassName;
|
||||
@Field(3)
|
||||
public String expandedControllerActivityClassName;
|
||||
@Field(4)
|
||||
public IImagePicker imagePicker;
|
||||
@Field(5)
|
||||
public NotificationOptions notificationOptions;
|
||||
@Field(6)
|
||||
public boolean bool6;
|
||||
@Field(7)
|
||||
public boolean bool7;
|
||||
|
||||
public static Creator<CastMediaOptions> CREATOR = new AutoCreator<CastMediaOptions>(CastMediaOptions.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.KeyEvent;
|
||||
import com.google.android.gms.cast.framework.CastContext;
|
||||
import com.google.android.gms.cast.framework.CastSession;
|
||||
import com.google.android.gms.cast.framework.Session;
|
||||
import com.google.android.gms.cast.framework.SessionManager;
|
||||
|
||||
public class MediaIntentReceiver extends BroadcastReceiver {
|
||||
/**
|
||||
* The action for ending the current session and disconnecting from the receiver app.
|
||||
*/
|
||||
public static final String ACTION_DISCONNECT = "com.google.android.gms.cast.framework.action.DISCONNECT";
|
||||
/**
|
||||
* The action for forwarding the current item. When building an Intent with this action, use {@link #EXTRA_SKIP_STEP_MS} to set the
|
||||
* time to forward in milliseconds.
|
||||
*/
|
||||
public static final String ACTION_FORWARD = "com.google.android.gms.cast.framework.action.FORWARD";
|
||||
/**
|
||||
* The action for rewinding the current item. When building an Intent with this action, use {@link #EXTRA_SKIP_STEP_MS} to set the
|
||||
* time to rewind in milliseconds.
|
||||
*/
|
||||
public static final String ACTION_REWIND = "com.google.android.gms.cast.framework.action.REWIND";
|
||||
/**
|
||||
* The action for skipping to the next item in the queue.
|
||||
*/
|
||||
public static final String ACTION_SKIP_NEXT = "com.google.android.gms.cast.framework.action.SKIP_NEXT";
|
||||
/**
|
||||
* The action for skipping to the previous item in the queue.
|
||||
*/
|
||||
public static final String ACTION_SKIP_PREV = "com.google.android.gms.cast.framework.action.SKIP_PREV";
|
||||
/**
|
||||
* The action for ending the current session and stopping the receiver app.
|
||||
*/
|
||||
public static final String ACTION_STOP_CASTING = "com.google.android.gms.cast.framework.action.STOP_CASTING";
|
||||
/**
|
||||
* The action for toggling remote media playback.
|
||||
*/
|
||||
public static final String ACTION_TOGGLE_PLAYBACK = "com.google.android.gms.cast.framework.action.TOGGLE_PLAYBACK";
|
||||
/**
|
||||
* The extra key for specifying how much the currently playing item should be forwarded or rewinded to handle
|
||||
* {@link #ACTION_FORWARD} and {@link #ACTION_REWIND}.
|
||||
*/
|
||||
public static final String EXTRA_SKIP_STEP_MS = "googlecast-extra_skip_step_ms";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SessionManager sessionManager = CastContext.getSharedInstance(context).getSessionManager();
|
||||
Session currentSession = sessionManager.getCurrentSession();
|
||||
if (intent.getAction() != null && currentSession != null) {
|
||||
switch (intent.getAction()) {
|
||||
case ACTION_TOGGLE_PLAYBACK:
|
||||
onReceiveActionTogglePlayback(currentSession);
|
||||
break;
|
||||
case ACTION_SKIP_NEXT:
|
||||
onReceiveActionSkipNext(currentSession);
|
||||
break;
|
||||
case ACTION_SKIP_PREV:
|
||||
onReceiveActionSkipPrev(currentSession);
|
||||
break;
|
||||
case ACTION_FORWARD:
|
||||
onReceiveActionForward(currentSession, intent.getLongExtra(EXTRA_SKIP_STEP_MS, 0));
|
||||
break;
|
||||
case ACTION_REWIND:
|
||||
onReceiveActionRewind(currentSession, intent.getLongExtra(EXTRA_SKIP_STEP_MS, 0));
|
||||
break;
|
||||
case ACTION_STOP_CASTING:
|
||||
sessionManager.endCurrentSession(true);
|
||||
break;
|
||||
case ACTION_DISCONNECT:
|
||||
sessionManager.endCurrentSession(false);
|
||||
break;
|
||||
case Intent.ACTION_MEDIA_BUTTON:
|
||||
onReceiveActionMediaButton(currentSession, intent);
|
||||
break;
|
||||
default:
|
||||
onReceiveOtherAction(context, intent.getAction(), intent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #ACTION_FORWARD} is received. The default implementation forwards the current playing item by
|
||||
* {@code forwardStepMs} if {@code currentSession} is a {@link CastSession}. Subclasses can override this method to change the behavior
|
||||
* or handle other type of {@link Session}. Subclasses should call through to super to let the SDK handle the action if
|
||||
* {@code currentSession} is a {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
* @param forwardStepMs Time to forward in milliseconds.
|
||||
*/
|
||||
protected void onReceiveActionForward(Session currentSession, long forwardStepMs) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
// TODO Seek forwardStepMs
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link Intent#ACTION_MEDIA_BUTTON} is received. The default implementation toggles playback state if
|
||||
* {@code currentSession} is a {@link CastSession}. Subclasses can override this method to change the behavior or handle other type
|
||||
* of {@link Session}. Subclasses should call through to super to let the SDK handle the action if {@code currentSession} is a
|
||||
* {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
* @param intent The Intent of this action.
|
||||
*/
|
||||
protected void onReceiveActionMediaButton(Session currentSession, Intent intent) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
if (intent.hasExtra(Intent.EXTRA_KEY_EVENT)) {
|
||||
KeyEvent keyEvent = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN && keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
||||
// TODO Toggle Playback
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #ACTION_REWIND} is received. The default implementation forwards the current playing item by
|
||||
* {@code rewindStepMs} if {@code currentSession} is a {@link CastSession}. Subclasses can override this method to change the behavior or
|
||||
* handle other type of {@link Session}. Subclasses should call through to super to let the SDK handle the action if
|
||||
* {@code currentSession} is a {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
* @param rewindStepMs Time to rewind in milliseconds.
|
||||
*/
|
||||
protected void onReceiveActionRewind(Session currentSession, long rewindStepMs) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
// TODO Seek -rewindStepMs
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #ACTION_SKIP_NEXT} is received. The default implementation plays the next item in the queue if
|
||||
* {@code currentSession} is a {@link CastSession} and there is a next item. Subclasses can override this method to change the
|
||||
* behavior or handle other type of {@link Session}. Subclasses should call through to super to let the SDK handle the action if
|
||||
* {@code currentSession} is a {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
*/
|
||||
protected void onReceiveActionSkipNext(Session currentSession) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
// TODO Queue next
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #ACTION_SKIP_PREV} is received. The default implementation plays the previous item in the queue if
|
||||
* {@code currentSession} is a {@link CastSession} and there is a previous item. Subclasses can override this method to change the
|
||||
* behavior or handle other type of {@link Session}. Subclasses should call through to super to let the SDK handle the action if
|
||||
* {@code currentSession} is a {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
*/
|
||||
protected void onReceiveActionSkipPrev(Session currentSession) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
// TODO Queue prev
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link #ACTION_TOGGLE_PLAYBACK} is received. The default implementation toggles playback state if
|
||||
* {@code currentSession} is a {@link CastSession}. Subclasses can override this method to change the
|
||||
* behavior or handle other type of {@link Session}. Subclasses should call through to super to let the SDK handle the action if
|
||||
* {@code currentSession} is a {@link CastSession}
|
||||
*
|
||||
* @param currentSession The current {@link Session}.
|
||||
*/
|
||||
protected void onReceiveActionTogglePlayback(Session currentSession) {
|
||||
if (!(currentSession instanceof CastSession)) return;
|
||||
// TODO Toggle Playback
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Override {@link #onReceiveOtherAction(Context, String, Intent)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected void onReceiveOtherAction(String action, Intent intent) {
|
||||
onReceiveOtherAction(null, action, intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when other type of actions are received. The default implementation does nothing.
|
||||
*
|
||||
* @param context The Context in which the receiver is running.
|
||||
* @param action The action.
|
||||
* @param intent The Intent of this action.
|
||||
*/
|
||||
protected void onReceiveOtherAction(Context context, String action, Intent intent) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class MediaNotificationService extends Service {
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2018 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||
* See https://developers.google.com/readme/policies for details.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.cast.framework.media;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import org.microg.safeparcel.AutoSafeParcelable;
|
||||
|
||||
/**
|
||||
* Configuration parameters for building the media notification. The {@link NotificationOptions.Builder} is used to create an
|
||||
* instance of {@link NotificationOptions}, and so contains the corresponding setter methods.
|
||||
*/
|
||||
public class NotificationOptions extends AutoSafeParcelable {
|
||||
/**
|
||||
* Constant for notification skip step, ten seconds in milliseconds.
|
||||
*/
|
||||
public static final long SKIP_STEP_TEN_SECONDS_IN_MS = 10000;
|
||||
/**
|
||||
* Constant for notification skip step, thirty seconds in milliseconds.
|
||||
*/
|
||||
public static final long SKIP_STEP_THIRTY_SECONDS_IN_MS = 30000;
|
||||
|
||||
@Field(1)
|
||||
private int versionCode = 1;
|
||||
@Field(2)
|
||||
private List<String> actions;
|
||||
@Field(3)
|
||||
private int[] compatActionIndices;
|
||||
@Field(4)
|
||||
private long skipStepMs;
|
||||
@Field(5)
|
||||
private String targetActivityClassName;
|
||||
@Field(6)
|
||||
private int getSmallIconDrawableResId;
|
||||
@Field(7)
|
||||
private int getStopLiveStreamDrawableResId;
|
||||
@Field(8)
|
||||
private int getPauseDrawableResId;
|
||||
@Field(9)
|
||||
private int getPlayDrawableResId;
|
||||
@Field(10)
|
||||
private int getSkipNextDrawableResId;
|
||||
@Field(11)
|
||||
private int getSkipPrevDrawableResId;
|
||||
@Field(12)
|
||||
private int getForwardDrawableResId;
|
||||
@Field(13)
|
||||
private int getForward10DrawableResId;
|
||||
@Field(14)
|
||||
private int getForward30DrawableResId;
|
||||
@Field(15)
|
||||
private int getRewindDrawableResId;
|
||||
@Field(16)
|
||||
private int getRewind10DrawableResId;
|
||||
@Field(17)
|
||||
private int getRewind30DrawableResId;
|
||||
@Field(18)
|
||||
private int getDisconnectDrawableResId;
|
||||
@Field(19)
|
||||
private int imageSizeDimenResId;
|
||||
@Field(20)
|
||||
private int getCastingToDeviceStringResId;
|
||||
@Field(21)
|
||||
private int getStopLiveStreamTitleResId;
|
||||
@Field(22)
|
||||
private int pauseTitleResId;
|
||||
@Field(23)
|
||||
private int playTitleResId;
|
||||
@Field(24)
|
||||
private int skipNextTitleResId;
|
||||
@Field(25)
|
||||
private int skipPrevTitleResId;
|
||||
@Field(26)
|
||||
private int forwardTitleResId;
|
||||
@Field(27)
|
||||
private int forward10TitleResId;
|
||||
@Field(28)
|
||||
private int forward30TitleResId;
|
||||
@Field(29)
|
||||
private int rewindTitleResId;
|
||||
@Field(30)
|
||||
private int rewind10TitleResId;
|
||||
@Field(31)
|
||||
private int rewind30TitleResId;
|
||||
@Field(32)
|
||||
private int disconnectTitleResId;
|
||||
@Field(33)
|
||||
private INotificationActionsProvider notificationActionsProvider;
|
||||
@Field(34)
|
||||
private boolean skipToPrevSlotReserved;
|
||||
@Field(35)
|
||||
private boolean skipToNextSlotReserved;
|
||||
|
||||
/**
|
||||
* Returns the list of actions to show in the notification.
|
||||
*/
|
||||
public List<String> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount to jump if {@link MediaIntentReceiver#ACTION_FORWARD} or {@link MediaIntentReceiver#ACTION_REWIND}
|
||||
* are included in the notification actions. Any tap on those actions will result in moving the media position forward or
|
||||
* backward by {@code skipStepMs} milliseconds. The default value is {@link #SKIP_STEP_TEN_SECONDS_IN_MS}.
|
||||
*/
|
||||
public long getSkipStepMs() {
|
||||
return skipStepMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the {@link Activity} that will be launched when user taps on the content area of the notification.
|
||||
*/
|
||||
public String getTargetActivityClassName() {
|
||||
return targetActivityClassName;
|
||||
}
|
||||
|
||||
public static Creator<NotificationOptions> CREATOR = new AutoCreator<NotificationOptions>(NotificationOptions.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.cast;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.ICastContext;
|
||||
import com.google.android.gms.cast.framework.IReconnectionService;
|
||||
import com.google.android.gms.cast.framework.ModuleUnavailableException;
|
||||
import com.google.android.gms.cast.framework.internal.ICastDynamiteModule;
|
||||
import com.google.android.gms.cast.framework.internal.IMediaRouter;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
import com.google.android.gms.dynamite.DynamiteModule;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CastDynamiteModule {
|
||||
public static ICastContext newCastContext(Context context, CastOptions castOptions, IMediaRouter mediaRouter, Map<String, IBinder> sessionProviderMap) throws ModuleUnavailableException, RemoteException {
|
||||
return getInterface(context).newCastContextImpl(ObjectWrapper.wrap(context), castOptions, mediaRouter, sessionProviderMap);
|
||||
}
|
||||
|
||||
public static IReconnectionService newReconnectionService(Service service, IObjectWrapper sessionManager, IObjectWrapper discoveryManager) {
|
||||
try {
|
||||
return getInterface(service.getApplicationContext()).newReconnectionServiceImpl(ObjectWrapper.wrap(service), sessionManager, discoveryManager);
|
||||
} catch (RemoteException | ModuleUnavailableException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ICastDynamiteModule getInterface(Context context) throws ModuleUnavailableException {
|
||||
try {
|
||||
IBinder binder = DynamiteModule.load(context, DynamiteModule.PREFER_REMOTE, "com.google.android.gms.cast.framework.dynamite").instantiate("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl");
|
||||
return ICastDynamiteModule.Stub.asInterface(binder);
|
||||
} catch (DynamiteModule.LoadingException e) {
|
||||
throw new ModuleUnavailableException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.cast;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.gms.cast.CastMediaControlIntent;
|
||||
import com.google.android.gms.cast.framework.CastOptions;
|
||||
import com.google.android.gms.cast.framework.Session;
|
||||
import com.google.android.gms.cast.framework.SessionProvider;
|
||||
|
||||
public class CastSessionProvider extends SessionProvider {
|
||||
private CastOptions castOptions;
|
||||
|
||||
public CastSessionProvider(Context applicationContext, CastOptions castOptions) {
|
||||
super(applicationContext, castOptions.getSupportedNamespaces().isEmpty() ? CastMediaControlIntent.categoryForCast(castOptions.getReceiverApplicationId()) : CastMediaControlIntent.categoryForCast(castOptions.getReceiverApplicationId(), castOptions.getSupportedNamespaces()));
|
||||
this.castOptions = castOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session createSession(String sessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSessionRecoverable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.cast;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import com.google.android.gms.cast.framework.ISessionProvider;
|
||||
import com.google.android.gms.cast.framework.SessionProvider;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
import org.microg.gms.common.Constants;
|
||||
|
||||
public class ISessionProviderImpl extends ISessionProvider.Stub {
|
||||
private SessionProvider delegate;
|
||||
|
||||
public ISessionProviderImpl(SessionProvider delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getSession(String sessionId) throws RemoteException {
|
||||
return ObjectWrapper.wrap(delegate.createSession(sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSessionRecoverable() throws RemoteException {
|
||||
return delegate.isSessionRecoverable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() throws RemoteException {
|
||||
return delegate.getCategory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSupportedVersion() throws RemoteException {
|
||||
return Constants.GMS_VERSION_CODE;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue