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

Commit 5ae099b9 authored by Xin Li's avatar Xin Li Committed by Android (Google) Code Review
Browse files

Merge "Merge SP1A.210812.016" into stage-aosp-master

parents 2c500e21 8891d703
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ filegroup {
    srcs: [
        "java/android/media/ApplicationMediaCapabilities.java",
        "java/android/media/MediaFeature.java",
        "java/android/media/MediaTranscodeManager.java",
        "java/android/media/MediaTranscodingManager.java",
    ],
    path: "java",
}
+19 −19
Original line number Diff line number Diff line
// Signature format: 2.0
package android.media {

  public final class MediaTranscodeManager {
    method @Nullable public android.media.MediaTranscodeManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener);
  public final class MediaTranscodingManager {
    method @Nullable public android.media.MediaTranscodingManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodingManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodingManager.OnTranscodingFinishedListener);
  }

  @java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
    method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingSession);
  @java.lang.FunctionalInterface public static interface MediaTranscodingManager.OnTranscodingFinishedListener {
    method public void onTranscodingFinished(@NonNull android.media.MediaTranscodingManager.TranscodingSession);
  }

  public abstract static class MediaTranscodeManager.TranscodingRequest {
  public abstract static class MediaTranscodingManager.TranscodingRequest {
    method public int getClientPid();
    method public int getClientUid();
    method @Nullable public android.os.ParcelFileDescriptor getDestinationFileDescriptor();
@@ -18,13 +18,13 @@ package android.media {
    method @NonNull public android.net.Uri getSourceUri();
  }

  public static class MediaTranscodeManager.TranscodingRequest.VideoFormatResolver {
    ctor public MediaTranscodeManager.TranscodingRequest.VideoFormatResolver(@NonNull android.media.ApplicationMediaCapabilities, @NonNull android.media.MediaFormat);
  public static class MediaTranscodingManager.TranscodingRequest.VideoFormatResolver {
    ctor public MediaTranscodingManager.TranscodingRequest.VideoFormatResolver(@NonNull android.media.ApplicationMediaCapabilities, @NonNull android.media.MediaFormat);
    method @Nullable public android.media.MediaFormat resolveVideoFormat();
    method public boolean shouldTranscode();
  }

  public static final class MediaTranscodeManager.TranscodingSession {
  public static final class MediaTranscodingManager.TranscodingSession {
    method public boolean addClientUid(int);
    method public void cancel();
    method @NonNull public java.util.List<java.lang.Integer> getClientUids();
@@ -33,7 +33,7 @@ package android.media {
    method public int getResult();
    method public int getSessionId();
    method public int getStatus();
    method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
    method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener);
    field public static final int ERROR_DROPPED_BY_SERVICE = 1; // 0x1
    field public static final int ERROR_NONE = 0; // 0x0
    field public static final int ERROR_SERVICE_DIED = 2; // 0x2
@@ -47,21 +47,21 @@ package android.media {
    field public static final int STATUS_RUNNING = 2; // 0x2
  }

  @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener {
    method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingSession, @IntRange(from=0, to=100) int);
  @java.lang.FunctionalInterface public static interface MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener {
    method public void onProgressUpdate(@NonNull android.media.MediaTranscodingManager.TranscodingSession, @IntRange(from=0, to=100) int);
  }

  public static final class MediaTranscodeManager.VideoTranscodingRequest extends android.media.MediaTranscodeManager.TranscodingRequest {
  public static final class MediaTranscodingManager.VideoTranscodingRequest extends android.media.MediaTranscodingManager.TranscodingRequest {
    method @NonNull public android.media.MediaFormat getVideoTrackFormat();
  }

  public static final class MediaTranscodeManager.VideoTranscodingRequest.Builder {
    ctor public MediaTranscodeManager.VideoTranscodingRequest.Builder(@NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.media.MediaFormat);
    method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest build();
    method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setClientPid(int);
    method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setClientUid(int);
    method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setDestinationFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
    method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setSourceFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
  public static final class MediaTranscodingManager.VideoTranscodingRequest.Builder {
    ctor public MediaTranscodingManager.VideoTranscodingRequest.Builder(@NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.media.MediaFormat);
    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest build();
    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientPid(int);
    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientUid(int);
    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setDestinationFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setSourceFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
  }

}
+2 −2
Original line number Diff line number Diff line
@@ -75,8 +75,8 @@ public class MediaFrameworkInitializer {
    public static void registerServiceWrappers() {
        SystemServiceRegistry.registerContextAwareService(
                Context.MEDIA_TRANSCODING_SERVICE,
                MediaTranscodeManager.class,
                context -> new MediaTranscodeManager(context)
                MediaTranscodingManager.class,
                context -> new MediaTranscodingManager(context)
        );
        if (SdkLevel.isAtLeastS()) {
            SystemServiceRegistry.registerContextAwareService(
+11 −11
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ import java.util.concurrent.Executors;
/**
 Android 12 introduces Compatible media transcoding feature.  See
 <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
 Compatible media transcoding</a>. MediaTranscodeManager provides an interface to the system's media
 Compatible media transcoding</a>. MediaTranscodingManager provides an interface to the system's media
 transcoding service and can be used to transcode media files, e.g. transcoding a video from HEVC to
 AVC.

@@ -69,7 +69,7 @@ import java.util.concurrent.Executors;
 <p>
 To transcode a media file, first create a {@link TranscodingRequest} through its builder class
 {@link VideoTranscodingRequest.Builder}. Transcode requests are then enqueue to the manager through
 {@link MediaTranscodeManager#enqueueRequest(
 {@link MediaTranscodingManager#enqueueRequest(
         TranscodingRequest, Executor, OnTranscodingFinishedListener)}
 TranscodeRequest are processed based on client process's priority and request priority. When a
 transcode operation is completed the caller is notified via its
@@ -87,8 +87,8 @@ import java.util.concurrent.Executors;
 */
@MinSdk(Build.VERSION_CODES.S)
@SystemApi
public final class MediaTranscodeManager {
    private static final String TAG = "MediaTranscodeManager";
public final class MediaTranscodingManager {
    private static final String TAG = "MediaTranscodingManager";

    /** Maximum number of retry to connect to the service. */
    private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
@@ -127,7 +127,7 @@ public final class MediaTranscodeManager {
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    @NonNull private ITranscodingClient mTranscodingClient = null;
    private static MediaTranscodeManager sMediaTranscodeManager;
    private static MediaTranscodingManager sMediaTranscodingManager;

    private void handleTranscodingFinished(int sessionId, TranscodingResultParcel result) {
        synchronized (mPendingTranscodingSessions) {
@@ -306,7 +306,7 @@ public final class MediaTranscodeManager {
                }

                try {
                    // Do not set hasRetried for retry initiated by MediaTranscodeManager.
                    // Do not set hasRetried for retry initiated by MediaTranscodingManager.
                    session.retryInternal(false /*setHasRetried*/);
                } catch (Exception re) {
                    // TODO(hkuang): Return correct error code to the client.
@@ -423,7 +423,7 @@ public final class MediaTranscodeManager {
    /**
     * @hide
     */
    public MediaTranscodeManager(@NonNull Context context) {
    public MediaTranscodingManager(@NonNull Context context) {
        mContext = context;
        mContentResolver = mContext.getContentResolver();
        mPackageName = mContext.getPackageName();
@@ -1348,7 +1348,7 @@ public final class MediaTranscodeManager {
                    @IntRange(from = 0, to = 100) int progress);
        }

        private final MediaTranscodeManager mManager;
        private final MediaTranscodingManager mManager;
        private Executor mListenerExecutor;
        private OnTranscodingFinishedListener mListener;
        private int mSessionId = -1;
@@ -1374,7 +1374,7 @@ public final class MediaTranscodeManager {
        private final TranscodingRequest mRequest;

        private TranscodingSession(
                @NonNull MediaTranscodeManager manager,
                @NonNull MediaTranscodingManager manager,
                @NonNull TranscodingRequest request,
                @NonNull TranscodingSessionParcel parcel,
                @NonNull @CallbackExecutor Executor executor,
@@ -1675,10 +1675,10 @@ public final class MediaTranscodeManager {

    /**
     * Enqueues a TranscodingRequest for execution.
     * <p> Upon successfully accepting the request, MediaTranscodeManager will return a
     * <p> Upon successfully accepting the request, MediaTranscodingManager will return a
     * {@link TranscodingSession} to the client. Client should use {@link TranscodingSession} to
     * track the progress and get the result.
     * <p> MediaTranscodeManager will return null if fails to accept the request due to service
     * <p> MediaTranscodingManager will return null if fails to accept the request due to service
     * rebooting. Client could retry again after receiving null.
     *
     * @param transcodingRequest The TranscodingRequest to enqueue.
+124 −60
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.GuardedBy;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -78,6 +80,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -715,10 +718,21 @@ public final class BluetoothAdapter {
    private final IBluetoothManager mManagerService;
    private final AttributionSource mAttributionSource;

    // Yeah, keeping both mService and sService isn't pretty, but it's too late
    // in the current release for a major refactoring, so we leave them both
    // intact until this can be cleaned up in a future release

    @UnsupportedAppUsage
    @GuardedBy("mServiceLock")
    private IBluetooth mService;
    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();

    @GuardedBy("sServiceLock")
    private static boolean sServiceRegistered;
    @GuardedBy("sServiceLock")
    private static IBluetooth sService;
    private static final Object sServiceLock = new Object();

    private final Object mLock = new Object();
    private final Map<LeScanCallback, ScanCallback> mLeScanClients;
    private final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
@@ -792,19 +806,11 @@ public final class BluetoothAdapter {
     * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
     */
    BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) {
        if (managerService == null) {
            throw new IllegalArgumentException("bluetooth manager service is null");
        }
        try {
            mServiceLock.writeLock().lock();
            mService = managerService.registerAdapter(mManagerCallback);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        } finally {
            mServiceLock.writeLock().unlock();
        }
        mManagerService = Objects.requireNonNull(managerService);
        mAttributionSource = Objects.requireNonNull(attributionSource);
        synchronized (mServiceLock.writeLock()) {
            mService = getBluetoothService(mManagerCallback);
        }
        mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
        mToken = new Binder(DESCRIPTOR);
    }
@@ -3171,21 +3177,16 @@ public final class BluetoothAdapter {
        }
    }

    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final IBluetoothManagerCallback mManagerCallback =
    private static final IBluetoothManagerCallback sManagerCallback =
            new IBluetoothManagerCallback.Stub() {
                @SuppressLint("AndroidFrameworkRequiresPermission")
                public void onBluetoothServiceUp(IBluetooth bluetoothService) {
                    if (DBG) {
                        Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
                    }

                    mServiceLock.writeLock().lock();
                    mService = bluetoothService;
                    mServiceLock.writeLock().unlock();

                    synchronized (mProxyServiceStateCallbacks) {
                        for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
                    synchronized (sServiceLock) {
                        sService = bluetoothService;
                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
                            try {
                                if (cb != null) {
                                    cb.onBluetoothServiceUp(bluetoothService);
@@ -3197,6 +3198,56 @@ public final class BluetoothAdapter {
                            }
                        }
                    }
                }

                public void onBluetoothServiceDown() {
                    if (DBG) {
                        Log.d(TAG, "onBluetoothServiceDown");
                    }

                    synchronized (sServiceLock) {
                        sService = null;
                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
                            try {
                                if (cb != null) {
                                    cb.onBluetoothServiceDown();
                                } else {
                                    Log.d(TAG, "onBluetoothServiceDown: cb is null!");
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "", e);
                            }
                        }
                    }
                }

                public void onBrEdrDown() {
                    if (VDBG) {
                        Log.i(TAG, "onBrEdrDown");
                    }

                    synchronized (sServiceLock) {
                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
                            try {
                                if (cb != null) {
                                    cb.onBrEdrDown();
                                } else {
                                    Log.d(TAG, "onBrEdrDown: cb is null!");
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "", e);
                            }
                        }
                    }
                }
            };

    private final IBluetoothManagerCallback mManagerCallback =
            new IBluetoothManagerCallback.Stub() {
                public void onBluetoothServiceUp(IBluetooth bluetoothService) {
                    synchronized (mServiceLock.writeLock()) {
                        mService = bluetoothService;
                    }
                    synchronized (mMetadataListeners) {
                        mMetadataListeners.forEach((device, pair) -> {
                            try {
@@ -3221,12 +3272,7 @@ public final class BluetoothAdapter {
                }

                public void onBluetoothServiceDown() {
                    if (DBG) {
                        Log.d(TAG, "onBluetoothServiceDown: " + mService);
                    }

                    try {
                        mServiceLock.writeLock().lock();
                    synchronized (mServiceLock.writeLock()) {
                        mService = null;
                        if (mLeScanClients != null) {
                            mLeScanClients.clear();
@@ -3237,29 +3283,10 @@ public final class BluetoothAdapter {
                        if (mBluetoothLeScanner != null) {
                            mBluetoothLeScanner.cleanup();
                        }
                    } finally {
                        mServiceLock.writeLock().unlock();
                    }

                    synchronized (mProxyServiceStateCallbacks) {
                        for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
                            try {
                                if (cb != null) {
                                    cb.onBluetoothServiceDown();
                                } else {
                                    Log.d(TAG, "onBluetoothServiceDown: cb is null!");
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "", e);
                            }
                        }
                    }
                }

                public void onBrEdrDown() {
                    if (VDBG) {
                        Log.i(TAG, "onBrEdrDown: " + mService);
                    }
                }
            };

@@ -3494,15 +3521,12 @@ public final class BluetoothAdapter {

    protected void finalize() throws Throwable {
        try {
            mManagerService.unregisterAdapter(mManagerCallback);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            removeServiceStateCallback(mManagerCallback);
        } finally {
            super.finalize();
        }
    }


    /**
     * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
     * <p>Alphabetic characters must be uppercase to be valid.
@@ -3566,24 +3590,64 @@ public final class BluetoothAdapter {
        return mAttributionSource;
    }

    private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
            new ArrayList<IBluetoothManagerCallback>();
    @GuardedBy("sServiceLock")
    private static final WeakHashMap<IBluetoothManagerCallback, Void> sProxyServiceStateCallbacks =
            new WeakHashMap<>();

    /*package*/ IBluetooth getBluetoothService() {
        synchronized (sServiceLock) {
            if (sProxyServiceStateCallbacks.isEmpty()) {
                throw new IllegalStateException(
                        "Anonymous service access requires at least one lifecycle in process");
            }
            return sService;
        }
    }

    @UnsupportedAppUsage
    /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
        synchronized (mProxyServiceStateCallbacks) {
            if (cb == null) {
                Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
            } else if (!mProxyServiceStateCallbacks.contains(cb)) {
                mProxyServiceStateCallbacks.add(cb);
            }
        Objects.requireNonNull(cb);
        synchronized (sServiceLock) {
            sProxyServiceStateCallbacks.put(cb, null);
            registerOrUnregisterAdapterLocked();
            return sService;
        }
        return mService;
    }

    /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
        synchronized (mProxyServiceStateCallbacks) {
            mProxyServiceStateCallbacks.remove(cb);
        Objects.requireNonNull(cb);
        synchronized (sServiceLock) {
            sProxyServiceStateCallbacks.remove(cb);
            registerOrUnregisterAdapterLocked();
        }
    }

    /**
     * Handle registering (or unregistering) a single process-wide
     * {@link IBluetoothManagerCallback} based on the presence of local
     * {@link #sProxyServiceStateCallbacks} clients.
     */
    @GuardedBy("sServiceLock")
    private void registerOrUnregisterAdapterLocked() {
        final boolean isRegistered = sServiceRegistered;
        final boolean wantRegistered = !sProxyServiceStateCallbacks.isEmpty();

        if (isRegistered != wantRegistered) {
            if (wantRegistered) {
                try {
                    sService = mManagerService.registerAdapter(sManagerCallback);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } else {
                try {
                    mManagerService.unregisterAdapter(sManagerCallback);
                    sService = null;
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            sServiceRegistered = wantRegistered;
        }
    }

Loading