Initial hlsmplayer application

This commit is contained in:
root
2026-09-27 17:13:02 +08:00
commit be5a40bfe3
1214 changed files with 315753 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
plugins { id("com.android.library") }
android {
namespace = "androidx.media3.database"
compileSdk = 36
defaultConfig { minSdk = 23 }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
api(project(":lib-common"))
implementation(libs.androidx.annotation)
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest>
<uses-sdk/>
</manifest>
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import android.database.SQLException;
import androidx.media3.common.util.UnstableApi;
import java.io.IOException;
/** An {@link IOException} whose cause is an {@link SQLException}. */
@UnstableApi
public final class DatabaseIOException extends IOException {
public DatabaseIOException(SQLException cause) {
super(cause);
}
public DatabaseIOException(SQLException cause, String message) {
super(message, cause);
}
}
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import androidx.media3.common.util.UnstableApi;
/**
* Provides {@link SQLiteDatabase} instances to media library components, which may read and write
* tables prefixed with {@link #TABLE_PREFIX}.
*/
@UnstableApi
public interface DatabaseProvider {
/** Prefix for tables that can be read and written by media library components. */
String TABLE_PREFIX = "ExoPlayer";
/**
* Creates and/or opens a database that will be used for reading and writing.
*
* <p>Once opened successfully, the database is cached, so you can call this method every time you
* need to write to the database. Errors such as bad permissions or a full disk may cause this
* method to fail, but future attempts may succeed if the problem is fixed.
*
* @throws SQLiteException If the database cannot be opened for writing.
* @return A read/write database object.
*/
SQLiteDatabase getWritableDatabase();
/**
* Creates and/or opens a database. This will be the same object returned by {@link
* #getWritableDatabase()} unless some problem, such as a full disk, requires the database to be
* opened read-only. In that case, a read-only database object will be returned. If the problem is
* fixed, a future call to {@link #getWritableDatabase()} may succeed, in which case the read-only
* database object will be closed and the read/write object will be returned in the future.
*
* <p>Once opened successfully, the database is cached, so you can call this method every time you
* need to read from the database.
*
* @throws SQLiteException If the database cannot be opened.
* @return A database object valid until {@link #getWritableDatabase()} is called.
*/
SQLiteDatabase getReadableDatabase();
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.media3.common.util.UnstableApi;
/** A {@link DatabaseProvider} that provides instances obtained from a {@link SQLiteOpenHelper}. */
@UnstableApi
public final class DefaultDatabaseProvider implements DatabaseProvider {
private final SQLiteOpenHelper sqliteOpenHelper;
/**
* @param sqliteOpenHelper An {@link SQLiteOpenHelper} from which to obtain database instances.
*/
public DefaultDatabaseProvider(SQLiteOpenHelper sqliteOpenHelper) {
this.sqliteOpenHelper = sqliteOpenHelper;
}
@Override
public SQLiteDatabase getWritableDatabase() {
return sqliteOpenHelper.getWritableDatabase();
}
@Override
public SQLiteDatabase getReadableDatabase() {
return sqliteOpenHelper.getReadableDatabase();
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import android.content.Context;
import androidx.media3.common.util.UnstableApi;
/**
* @deprecated Use {@link StandaloneDatabaseProvider}.
*/
@Deprecated
@UnstableApi
public final class ExoDatabaseProvider extends StandaloneDatabaseProvider {
public ExoDatabaseProvider(Context context) {
super(context);
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
/**
* An {@link SQLiteOpenHelper} that provides instances of a standalone database.
*
* <p>Suitable for use by applications that do not already have their own database, or that would
* prefer to keep tables used by media library components isolated in their own database. Other
* applications should prefer to use {@link DefaultDatabaseProvider} with their own {@link
* SQLiteOpenHelper}.
*/
// TODO: Make this class final when ExoDatabaseProvider is removed.
@UnstableApi
public class StandaloneDatabaseProvider extends SQLiteOpenHelper implements DatabaseProvider {
/** The file name used for the standalone database. */
public static final String DATABASE_NAME = "exoplayer_internal.db";
private static final int VERSION = 1;
private static final String TAG = "SADatabaseProvider";
/**
* Provides instances of the database located by passing {@link #DATABASE_NAME} to {@link
* Context#getDatabasePath(String)}.
*
* @param context Any context.
*/
public StandaloneDatabaseProvider(Context context) {
super(context.getApplicationContext(), DATABASE_NAME, /* factory= */ null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Features create their own tables.
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Features handle their own upgrades.
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
wipeDatabase(db);
}
/**
* Makes a best effort to wipe the existing database. The wipe may be incomplete if the database
* contains foreign key constraints.
*/
private static void wipeDatabase(SQLiteDatabase db) {
String[] columns = {"type", "name"};
try (Cursor cursor =
db.query(
"sqlite_master",
columns,
/* selection= */ null,
/* selectionArgs= */ null,
/* groupBy= */ null,
/* having= */ null,
/* orderBy= */ null)) {
while (cursor.moveToNext()) {
String type = cursor.getString(0);
String name = cursor.getString(1);
if (!"sqlite_sequence".equals(name)) {
// If it's not an SQL-controlled entity, drop it
String sql = "DROP " + type + " IF EXISTS " + name;
try {
db.execSQL(sql);
} catch (SQLException e) {
Log.e(TAG, "Error executing " + sql, e);
}
}
}
}
}
}
@@ -0,0 +1,183 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.database;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import androidx.annotation.IntDef;
import androidx.media3.common.MediaLibraryInfo;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Utility methods for accessing versions of media library database components. This allows them to
* be versioned independently to the version of the containing database.
*/
@UnstableApi
public final class VersionTable {
static {
MediaLibraryInfo.registerModule("media3.database");
}
/** Returned by {@link #getVersion(SQLiteDatabase, int, String)} if the version is unset. */
public static final int VERSION_UNSET = -1;
/** Version of tables used for offline functionality. */
public static final int FEATURE_OFFLINE = 0;
/** Version of tables used for cache content metadata. */
public static final int FEATURE_CACHE_CONTENT_METADATA = 1;
/** Version of tables used for cache file metadata. */
public static final int FEATURE_CACHE_FILE_METADATA = 2;
/** Version of tables used from external features. */
public static final int FEATURE_EXTERNAL = 1000;
private static final String TABLE_NAME = DatabaseProvider.TABLE_PREFIX + "Versions";
private static final String COLUMN_FEATURE = "feature";
private static final String COLUMN_INSTANCE_UID = "instance_uid";
private static final String COLUMN_VERSION = "version";
private static final String WHERE_FEATURE_AND_INSTANCE_UID_EQUALS =
COLUMN_FEATURE + " = ? AND " + COLUMN_INSTANCE_UID + " = ?";
private static final String PRIMARY_KEY =
"PRIMARY KEY (" + COLUMN_FEATURE + ", " + COLUMN_INSTANCE_UID + ")";
private static final String SQL_CREATE_TABLE_IF_NOT_EXISTS =
"CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME
+ " ("
+ COLUMN_FEATURE
+ " INTEGER NOT NULL,"
+ COLUMN_INSTANCE_UID
+ " TEXT NOT NULL,"
+ COLUMN_VERSION
+ " INTEGER NOT NULL,"
+ PRIMARY_KEY
+ ")";
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
FEATURE_OFFLINE,
FEATURE_CACHE_CONTENT_METADATA,
FEATURE_CACHE_FILE_METADATA,
FEATURE_EXTERNAL
})
private @interface Feature {}
private VersionTable() {}
/**
* Sets the version of a specified instance of a specified feature.
*
* @param writableDatabase The database to update.
* @param feature The feature.
* @param instanceUid The unique identifier of the instance of the feature.
* @param version The version.
* @throws DatabaseIOException If an error occurs executing the SQL.
*/
public static void setVersion(
SQLiteDatabase writableDatabase, @Feature int feature, String instanceUid, int version)
throws DatabaseIOException {
try {
writableDatabase.execSQL(SQL_CREATE_TABLE_IF_NOT_EXISTS);
ContentValues values = new ContentValues();
values.put(COLUMN_FEATURE, feature);
values.put(COLUMN_INSTANCE_UID, instanceUid);
values.put(COLUMN_VERSION, version);
writableDatabase.replaceOrThrow(TABLE_NAME, /* nullColumnHack= */ null, values);
} catch (SQLException e) {
throw new DatabaseIOException(e);
}
}
/**
* Removes the version of a specified instance of a feature.
*
* @param writableDatabase The database to update.
* @param feature The feature.
* @param instanceUid The unique identifier of the instance of the feature.
* @throws DatabaseIOException If an error occurs executing the SQL.
*/
public static void removeVersion(
SQLiteDatabase writableDatabase, @Feature int feature, String instanceUid)
throws DatabaseIOException {
try {
if (!Util.tableExists(writableDatabase, TABLE_NAME)) {
return;
}
writableDatabase.delete(
TABLE_NAME,
WHERE_FEATURE_AND_INSTANCE_UID_EQUALS,
featureAndInstanceUidArguments(feature, instanceUid));
} catch (SQLException e) {
throw new DatabaseIOException(e);
}
}
/**
* Returns the version of a specified instance of a feature, or {@link #VERSION_UNSET} if no
* version is set.
*
* @param database The database to query.
* @param feature The feature.
* @param instanceUid The unique identifier of the instance of the feature.
* @return The version, or {@link #VERSION_UNSET} if no version is set.
* @throws DatabaseIOException If an error occurs executing the SQL.
*/
public static int getVersion(SQLiteDatabase database, @Feature int feature, String instanceUid)
throws DatabaseIOException {
try {
if (!Util.tableExists(database, TABLE_NAME)) {
return VERSION_UNSET;
}
try (Cursor cursor =
database.query(
TABLE_NAME,
new String[] {COLUMN_VERSION},
WHERE_FEATURE_AND_INSTANCE_UID_EQUALS,
featureAndInstanceUidArguments(feature, instanceUid),
/* groupBy= */ null,
/* having= */ null,
/* orderBy= */ null)) {
if (cursor.getCount() == 0) {
return VERSION_UNSET;
}
cursor.moveToNext();
return cursor.getInt(/* COLUMN_VERSION index */ 0);
}
} catch (SQLException e) {
throw new DatabaseIOException(e);
}
}
private static String[] featureAndInstanceUidArguments(int feature, String instance) {
return new String[] {Integer.toString(feature), instance};
}
}
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package androidx.media3.database;
import androidx.media3.common.util.NonNullApi;