Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 845fa764 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Remove MediaPlayer2

Bug: 141546997
Test: build, boot
Change-Id: I1550c14f3a0967910809cc2415d10f62c967bd44
Merged-In: I1550c14f3a0967910809cc2415d10f62c967bd44
parent 80fd4450
Loading
Loading
Loading
Loading
+0 −20
Original line number Original line Diff line number Diff line
@@ -61,26 +61,6 @@ filegroup {
    path: "apex/java",
    path: "apex/java",
}
}


filegroup {
    name: "mediaplayer2-srcs",
    srcs: [
        "apex/java/android/media/CloseGuard.java",
        "apex/java/android/media/DataSourceCallback.java",
        "apex/java/android/media/DataSourceDesc.java",
        "apex/java/android/media/UriDataSourceDesc.java",
        "apex/java/android/media/FileDataSourceDesc.java",
        "apex/java/android/media/Media2Utils.java",
        "apex/java/android/media/MediaPlayer2Utils.java",
        "apex/java/android/media/MediaPlayer2.java",
        "apex/java/android/media/Media2HTTPService.java",
        "apex/java/android/media/Media2HTTPConnection.java",
        "apex/java/android/media/RoutingDelegate.java",
        "apex/java/android/media/BufferingParams.java",
        "apex/java/android/media/ProxyDataSourceCallback.java",
    ],
    path: "apex/java",
}

metalava_updatable_media_args = " --error UnhiddenSystemApi " +
metalava_updatable_media_args = " --error UnhiddenSystemApi " +
    "--hide RequiresPermission " +
    "--hide RequiresPermission " +
    "--hide MissingPermission --hide BroadcastBehavior " +
    "--hide MissingPermission --hide BroadcastBehavior " +
+0 −384
Original line number Original line Diff line number Diff line
/*
 * Copyright 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 android.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Data source descriptor.
 *
 * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
 * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
 *
 * @hide
 */
public class DataSourceDesc {
    // intentionally less than long.MAX_VALUE
    static final long LONG_MAX = 0x7ffffffffffffffL;

    // keep consistent with native code
    public static final long LONG_MAX_TIME_MS = LONG_MAX / 1000;
    /**
     * @hide
     */
    public static final long LONG_MAX_TIME_US = LONG_MAX_TIME_MS * 1000;

    public static final long POSITION_UNKNOWN = LONG_MAX_TIME_MS;

    private String mMediaId;
    private long mStartPositionMs = 0;
    private long mEndPositionMs = POSITION_UNKNOWN;

    DataSourceDesc(String mediaId, long startPositionMs, long endPositionMs) {
        mMediaId = mediaId;
        mStartPositionMs = startPositionMs;
        mEndPositionMs = endPositionMs;
    }

    /**
     * Releases the resources held by this {@code DataSourceDesc} object.
     */
    void close() {
    }

    // Have to declare protected for finalize() since it is protected
    // in the base class Object.
    @Override
    protected void finalize() throws Throwable {
        close();
    }

    /**
     * Return the media Id of data source.
     * @return the media Id of data source
     */
    public @Nullable String getMediaId() {
        return mMediaId;
    }

    /**
     * Return the position in milliseconds at which the playback will start.
     * @return the position in milliseconds at which the playback will start
     */
    public long getStartPosition() {
        return mStartPositionMs;
    }

    /**
     * Return the position in milliseconds at which the playback will end.
     * {@link #POSITION_UNKNOWN} means ending at the end of source content.
     * @return the position in milliseconds at which the playback will end
     */
    public long getEndPosition() {
        return mEndPositionMs;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("DataSourceDesc{");
        sb.append("mMediaId=").append(mMediaId);
        sb.append(", mStartPositionMs=").append(mStartPositionMs);
        sb.append(", mEndPositionMs=").append(mEndPositionMs);
        sb.append('}');
        return sb.toString();
    }

    /**
     * Builder for {@link DataSourceDesc}.
     * <p>
     * Here is an example where <code>Builder</code> is used to define the
     * {@link DataSourceDesc} to be used by a {@link MediaPlayer2} instance:
     *
     * <pre class="prettyprint">
     * DataSourceDesc newDSD = new DataSourceDesc.Builder()
     *         .setDataSource(context, uri, headers, cookies)
     *         .setStartPosition(1000)
     *         .setEndPosition(15000)
     *         .build();
     * mediaplayer2.setDataSourceDesc(newDSD);
     * </pre>
     */
    public static final class Builder {
        private static final int SOURCE_TYPE_UNKNOWN = 0;
        private static final int SOURCE_TYPE_URI = 1;
        private static final int SOURCE_TYPE_FILE = 2;

        private int mSourceType = SOURCE_TYPE_UNKNOWN;
        private String mMediaId;
        private long mStartPositionMs = 0;
        private long mEndPositionMs = POSITION_UNKNOWN;

        // For UriDataSourceDesc
        private Uri mUri;
        private Map<String, String> mHeader;
        private List<HttpCookie> mCookies;

        // For FileDataSourceDesc
        private ParcelFileDescriptor mPFD;
        private long mOffset = 0;
        private long mLength = FileDataSourceDesc.FD_LENGTH_UNKNOWN;

        /**
         * Constructs a new BuilderBase with the defaults.
         */
        public Builder() {
        }

        /**
         * Constructs a new BuilderBase from a given {@link DataSourceDesc} instance
         * @param dsd the {@link DataSourceDesc} object whose data will be reused
         * in the new BuilderBase.
         */
        public Builder(@Nullable DataSourceDesc dsd) {
            if (dsd == null) {
                return;
            }
            mMediaId = dsd.mMediaId;
            mStartPositionMs = dsd.mStartPositionMs;
            mEndPositionMs = dsd.mEndPositionMs;
            if (dsd instanceof FileDataSourceDesc) {
                mSourceType = SOURCE_TYPE_FILE;
                mPFD = ((FileDataSourceDesc) dsd).getParcelFileDescriptor();
                mOffset = ((FileDataSourceDesc) dsd).getOffset();
                mLength = ((FileDataSourceDesc) dsd).getLength();
            } else if (dsd instanceof UriDataSourceDesc) {
                mSourceType = SOURCE_TYPE_URI;
                mUri = ((UriDataSourceDesc) dsd).getUri();
                mHeader = ((UriDataSourceDesc) dsd).getHeaders();
                mCookies = ((UriDataSourceDesc) dsd).getCookies();
            } else {
                throw new IllegalStateException("Unknown source type:" + mSourceType);
            }
        }

        /**
         * Sets all fields that have been set in the {@link DataSourceDesc} object.
         * <code>IllegalStateException</code> will be thrown if there is conflict between fields.
         *
         * @return {@link DataSourceDesc}
         */
        @NonNull
        public DataSourceDesc build() {
            if (mSourceType == SOURCE_TYPE_UNKNOWN) {
                throw new IllegalStateException("Source is not set.");
            }
            if (mStartPositionMs > mEndPositionMs) {
                throw new IllegalStateException("Illegal start/end position: "
                    + mStartPositionMs + " : " + mEndPositionMs);
            }

            DataSourceDesc desc;
            if (mSourceType == SOURCE_TYPE_FILE) {
                desc = new FileDataSourceDesc(
                        mMediaId, mStartPositionMs, mEndPositionMs, mPFD, mOffset, mLength);
            } else if (mSourceType == SOURCE_TYPE_URI) {
                desc = new UriDataSourceDesc(
                        mMediaId, mStartPositionMs, mEndPositionMs, mUri, mHeader, mCookies);
            } else {
                throw new IllegalStateException("Unknown source type:" + mSourceType);
            }
            return desc;
        }

        /**
         * Sets the media Id of this data source.
         *
         * @param mediaId the media Id of this data source
         * @return the same Builder instance.
         */
        @NonNull
        public Builder setMediaId(@Nullable String mediaId) {
            mMediaId = mediaId;
            return this;
        }

        /**
         * Sets the start position in milliseconds at which the playback will start.
         * Any negative number is treated as 0.
         *
         * @param position the start position in milliseconds at which the playback will start
         * @return the same Builder instance.
         *
         */
        @NonNull
        public Builder setStartPosition(long position) {
            if (position < 0) {
                position = 0;
            }
            mStartPositionMs = position;
            return this;
        }

        /**
         * Sets the end position in milliseconds at which the playback will end.
         * Any negative number is treated as maximum duration {@link #LONG_MAX_TIME_MS}
         * of the data source
         *
         * @param position the end position in milliseconds at which the playback will end
         * @return the same Builder instance.
         */
        @NonNull
        public Builder setEndPosition(long position) {
            if (position < 0) {
                position = LONG_MAX_TIME_MS;
            }
            mEndPositionMs = position;
            return this;
        }

        /**
         * Sets the data source as a content Uri.
         *
         * @param uri the Content URI of the data you want to play
         * @return the same Builder instance.
         * @throws NullPointerException if context or uri is null.
         */
        @NonNull
        public Builder setDataSource(@NonNull Uri uri) {
            setSourceType(SOURCE_TYPE_URI);
            Media2Utils.checkArgument(uri != null, "uri cannot be null");
            mUri = uri;
            return this;
        }

        /**
         * Sets the data source as a content Uri.
         *
         * To provide cookies for the subsequent HTTP requests, you can install your own default
         * cookie handler and use other variants of setDataSource APIs instead. Alternatively, you
         * can use this API to pass the cookies as a list of HttpCookie. If the app has not
         * installed a CookieHandler already, {@link MediaPlayer2} will create a CookieManager
         * and populates its CookieStore with the provided cookies when this data source is passed
         * to {@link MediaPlayer2}. If the app has installed its own handler already, the handler
         * is required to be of CookieManager type such that {@link MediaPlayer2} can update the
         * manager’s CookieStore.
         *
         *  <p><strong>Note</strong> that the cross domain redirection is allowed by default,
         * but that can be changed with key/value pairs through the headers parameter with
         * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
         * disallow or allow cross domain redirection.
         *
         * @param uri the Content URI of the data you want to play
         * @param headers the headers to be sent together with the request for the data
         *                The headers must not include cookies. Instead, use the cookies param.
         * @param cookies the cookies to be sent together with the request
         * @return the same Builder instance.
         * @throws NullPointerException if context or uri is null.
         * @throws IllegalArgumentException if the cookie handler is not of CookieManager type
         *                                  when cookies are provided.
         */
        @NonNull
        public Builder setDataSource(@NonNull Uri uri, @Nullable Map<String, String> headers,
                @Nullable List<HttpCookie> cookies) {
            setSourceType(SOURCE_TYPE_URI);
            Media2Utils.checkArgument(uri != null, "uri cannot be null");
            if (cookies != null) {
                CookieHandler cookieHandler = CookieHandler.getDefault();
                if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) {
                    throw new IllegalArgumentException(
                            "The cookie handler has to be of CookieManager type "
                                    + "when cookies are provided.");
                }
            }

            mUri = uri;
            if (headers != null) {
                mHeader = new HashMap<String, String>(headers);
            }
            if (cookies != null) {
                mCookies = new ArrayList<HttpCookie>(cookies);
            }
            return this;
        }

        /**
         * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
         * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc}
         * created by this builder is passed to {@link MediaPlayer2} via
         * {@link MediaPlayer2#setDataSource},
         * {@link MediaPlayer2#setNextDataSource} or
         * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
         * close the ParcelFileDescriptor.
         *
         * @param pfd the ParcelFileDescriptor for the file to play
         * @return the same Builder instance.
         * @throws NullPointerException if pfd is null.
         */
        @NonNull
        public Builder setDataSource(@NonNull ParcelFileDescriptor pfd) {
            setSourceType(SOURCE_TYPE_FILE);
            Media2Utils.checkArgument(pfd != null, "pfd cannot be null.");
            mPFD = pfd;
            return this;
        }

        /**
         * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
         * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc}
         * created by this builder is passed to {@link MediaPlayer2} via
         * {@link MediaPlayer2#setDataSource},
         * {@link MediaPlayer2#setNextDataSource} or
         * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
         * close the ParcelFileDescriptor.
         *
         * Any negative number for offset is treated as 0.
         * Any negative number for length is treated as maximum length of the data source.
         *
         * @param pfd the ParcelFileDescriptor for the file to play
         * @param offset the offset into the file where the data to be played starts, in bytes
         * @param length the length in bytes of the data to be played
         * @return the same Builder instance.
         * @throws NullPointerException if pfd is null.
         */
        @NonNull
        public Builder setDataSource(
                @NonNull ParcelFileDescriptor pfd, long offset, long length) {
            setSourceType(SOURCE_TYPE_FILE);
            if (pfd == null) {
                throw new NullPointerException("pfd cannot be null.");
            }
            if (offset < 0) {
                offset = 0;
            }
            if (length < 0) {
                length = FileDataSourceDesc.FD_LENGTH_UNKNOWN;
            }
            mPFD = pfd;
            mOffset = offset;
            mLength = length;
            return this;
        }

        private void setSourceType(int type) {
            if (mSourceType != SOURCE_TYPE_UNKNOWN) {
                throw new IllegalStateException("Source is already set. type=" + mSourceType);
            }
            mSourceType = type;
        }
    }
}
+0 −134
Original line number Original line Diff line number Diff line
/*
 * Copyright 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 android.media;

import android.annotation.NonNull;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import java.io.IOException;

/**
 * Structure of data source descriptor for sources using file descriptor.
 *
 * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
 * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
 *
 * <p>Users should use {@link Builder} to create {@link FileDataSourceDesc}.
 * @hide
 */
public class FileDataSourceDesc extends DataSourceDesc {
    private static final String TAG = "FileDataSourceDesc";

    /**
     * Used when the length of file descriptor is unknown.
     *
     * @see #getLength()
     */
    public static final long FD_LENGTH_UNKNOWN = LONG_MAX;

    private ParcelFileDescriptor mPFD;
    private long mOffset = 0;
    private long mLength = FD_LENGTH_UNKNOWN;
    private int mCount = 0;
    private boolean mClosed = false;

    FileDataSourceDesc(String mediaId, long startPositionMs, long endPositionMs,
            ParcelFileDescriptor pfd, long offset, long length) {
        super(mediaId, startPositionMs, endPositionMs);
        mPFD = pfd;
        mOffset = offset;
        mLength = length;
    }

    /**
     * Releases the resources held by this {@code FileDataSourceDesc} object.
     */
    @Override
    void close() {
        super.close();
        decCount();
    }

    /**
     * Decrements usage count by {@link MediaPlayer2}.
     * If this is the last usage, also releases the file descriptor held by this
     * {@code FileDataSourceDesc} object.
     */
    void decCount() {
        synchronized (this) {
            --mCount;
            if (mCount > 0) {
                return;
            }

            try {
                mPFD.close();
                mClosed = true;
            } catch (IOException e) {
                Log.e(TAG, "failed to close pfd: " + e);
            }
        }
    }

    /**
     * Increments usage count by {@link MediaPlayer2} if PFD has not been closed.
     */
    void incCount() {
        synchronized (this) {
            if (!mClosed) {
                ++mCount;
            }
        }
    }

    /**
     * Return the status of underline ParcelFileDescriptor
     * @return true if underline ParcelFileDescriptor is closed, false otherwise.
     */
    boolean isPFDClosed() {
        synchronized (this) {
            return mClosed;
        }
    }

    /**
     * Return the ParcelFileDescriptor of this data source.
     * @return the ParcelFileDescriptor of this data source
     */
    public @NonNull ParcelFileDescriptor getParcelFileDescriptor() {
        return mPFD;
    }

    /**
     * Return the offset associated with the ParcelFileDescriptor of this data source.
     * It's meaningful only when it has been set by the {@link Builder}.
     * @return the offset associated with the ParcelFileDescriptor of this data source
     */
    public long getOffset() {
        return mOffset;
    }

    /**
     * Return the content length associated with the ParcelFileDescriptor of this data source.
     * {@link #FD_LENGTH_UNKNOWN} means same as the length of source content.
     * @return the content length associated with the ParcelFileDescriptor of this data source
     */
    public long getLength() {
        return mLength;
    }
}
+0 −385

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −58
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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 android.media;

import android.util.Log;

import java.net.HttpCookie;
import java.util.List;

/** @hide */
public class Media2HTTPService {
    private static final String TAG = "Media2HTTPService";
    private List<HttpCookie> mCookies;
    private Boolean mCookieStoreInitialized = new Boolean(false);

    public Media2HTTPService(List<HttpCookie> cookies) {
        mCookies = cookies;
        Log.v(TAG, "Media2HTTPService(" + this + "): Cookies: " + cookies);
    }

    public Media2HTTPConnection makeHTTPConnection() {

        synchronized (mCookieStoreInitialized) {
            Media2Utils.storeCookies(mCookies);
        }

        return new Media2HTTPConnection();
    }

    /* package private */ static Media2HTTPService createHTTPService(String path) {
        return createHTTPService(path, null);
    }

    // when cookies are provided
    static Media2HTTPService createHTTPService(String path, List<HttpCookie> cookies) {
        if (path.startsWith("http://") || path.startsWith("https://")) {
            return (new Media2HTTPService(cookies));
        } else if (path.startsWith("widevine://")) {
            Log.d(TAG, "Widevine classic is no longer supported");
        }

        return null;
    }
}
Loading