diff options
4 files changed, 103 insertions, 26 deletions
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java index 7e4799cb477a..6eb93469f975 100644 --- a/apex/media/framework/java/android/media/MediaTranscodingManager.java +++ b/apex/media/framework/java/android/media/MediaTranscodingManager.java @@ -946,6 +946,8 @@ public final class MediaTranscodingManager { * * @return the video track format to be used if transcoding should be performed, * and null otherwise. + * @throws IllegalArgumentException if the hinted source video format contains invalid + * parameters. */ @Nullable public MediaFormat resolveVideoFormat() { @@ -956,20 +958,19 @@ public final class MediaTranscodingManager { MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint); videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); - int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH); - int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT); + int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1); + int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1); if (width <= 0 || height <= 0) { throw new IllegalArgumentException( "Source Width and height must be larger than 0"); } - float frameRate = 30.0f; // default to 30fps. - if (mSrcVideoFormatHint.containsKey(MediaFormat.KEY_FRAME_RATE)) { - frameRate = mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE); - if (frameRate <= 0) { - throw new IllegalArgumentException( - "frameRate must be larger than 0"); - } + float frameRate = + mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0) + .floatValue(); + if (frameRate <= 0) { + throw new IllegalArgumentException( + "frameRate must be larger than 0"); } int bitrate = getAVCBitrate(width, height, frameRate); diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index d3d6e03c9bc7..6f30ac3901e1 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -18,6 +18,7 @@ package com.android.systemui.controls.ui import android.annotation.MainThread import android.app.Dialog +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -88,7 +89,7 @@ class ControlActionCoordinatorImpl @Inject constructor( bouncerOrRun(createAction(cvh.cws.ci.controlId, { cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) if (cvh.usePanel()) { - showDetail(cvh, control.getAppIntent().getIntent()) + showDetail(cvh, control.getAppIntent()) } else { cvh.action(CommandAction(templateId)) } @@ -116,7 +117,7 @@ class ControlActionCoordinatorImpl @Inject constructor( // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - showDetail(cvh, it.getAppIntent().getIntent()) + showDetail(cvh, it.getAppIntent()) } }, false /* blockable */)) } @@ -167,10 +168,10 @@ class ControlActionCoordinatorImpl @Inject constructor( bgExecutor.execute { vibrator.vibrate(effect) } } - private fun showDetail(cvh: ControlViewHolder, intent: Intent) { + private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) { bgExecutor.execute { val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities( - intent, + pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY ) @@ -178,7 +179,7 @@ class ControlActionCoordinatorImpl @Inject constructor( // make sure the intent is valid before attempting to open the dialog if (activities.isNotEmpty() && taskViewFactory.isPresent) { taskViewFactory.get().create(context, uiExecutor, { - dialog = DetailDialog(activityContext, it, intent, cvh).also { + dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also { it.setOnDismissListener { _ -> dialog = null } it.show() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index 8a47a36de8c4..4758ab04e2e5 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -43,7 +43,7 @@ import com.android.wm.shell.TaskView class DetailDialog( val activityContext: Context?, val taskView: TaskView, - val intent: Intent, + val pendingIntent: PendingIntent, val cvh: ControlViewHolder ) : Dialog( activityContext ?: cvh.context, @@ -59,6 +59,14 @@ class DetailDialog( var detailTaskId = INVALID_TASK_ID + private val fillInIntent = Intent().apply { + putExtra(EXTRA_USE_PANEL, true) + + // Apply flags to make behaviour match documentLaunchMode=always. + addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) + addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + } + fun removeDetailTask() { if (detailTaskId == INVALID_TASK_ID) return ActivityTaskManager.getInstance().removeTask(detailTaskId) @@ -67,13 +75,6 @@ class DetailDialog( val stateCallback = object : TaskView.Listener { override fun onInitialized() { - val launchIntent = Intent(intent) - launchIntent.putExtra(EXTRA_USE_PANEL, true) - - // Apply flags to make behaviour match documentLaunchMode=always. - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) - launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) - val options = activityContext?.let { ActivityOptions.makeCustomAnimation( it, @@ -82,9 +83,8 @@ class DetailDialog( ) } ?: ActivityOptions.makeBasic() taskView.startActivity( - PendingIntent.getActivity(context, 0, launchIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE), - null /* fillInIntent */, + pendingIntent, + fillInIntent, options, getTaskViewBounds() ) @@ -97,6 +97,9 @@ class DetailDialog( override fun onTaskCreated(taskId: Int, name: ComponentName?) { detailTaskId = taskId + requireViewById<ViewGroup>(R.id.controls_activity_view).apply { + setAlpha(1f) + } } override fun onReleased() { @@ -121,6 +124,7 @@ class DetailDialog( requireViewById<ViewGroup>(R.id.controls_activity_view).apply { addView(taskView) + setAlpha(0f) } requireViewById<ImageView>(R.id.control_detail_close).apply { @@ -134,7 +138,7 @@ class DetailDialog( removeDetailTask() dismiss() context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) - v.context.startActivity(intent) + pendingIntent.send() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt new file mode 100644 index 000000000000..87b9172dcefc --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package com.android.systemui.controls.ui + +import android.app.PendingIntent +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.wm.shell.TaskView +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class DetailDialogTest : SysuiTestCase() { + + @Mock + private lateinit var taskView: TaskView + @Mock + private lateinit var controlViewHolder: ControlViewHolder + @Mock + private lateinit var pendingIntent: PendingIntent + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testPendingIntentIsUnModified() { + // GIVEN the dialog is created with a PendingIntent + val dialog = createDialog(pendingIntent) + + // WHEN the TaskView is initialized + dialog.stateCallback.onInitialized() + + // THEN the PendingIntent used to call startActivity is unmodified by systemui + verify(taskView).startActivity(eq(pendingIntent), any(), any(), any()) + } + + private fun createDialog(pendingIntent: PendingIntent): DetailDialog { + return DetailDialog( + mContext, + taskView, + pendingIntent, + controlViewHolder + ) + } +} |