Target SDK level 29 in AppRTCMobile.

Removes CAPTURE_VIDEO_OUTPUT permission since it is not needed
when using MediaProjection API and not allowed in Android Q.

This is a reland of af4f1b41277ebdf0d7386cbd2903abc709cbc183

Original change's description:
> Target SDK level 27 in AppRTCMobile.
>
> Implements the dynamic permission model required by the newer SDK and
> changes the theme.
>
> Bug: webrtc:8803
> Change-Id: I3ea23a25b27f196fcffd018c7cdd2ff6255b62d9
> Reviewed-on: https://webrtc-review.googlesource.com/44400
> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
> Reviewed-by: Anders Carlsson <andersc@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#21788}

Bug: webrtc:8803
Change-Id: Ie79d7f7b9e8fea255581d3b56772b5bb6fffff4c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/139881
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28137}
diff --git a/examples/androidapp/AndroidManifest.xml b/examples/androidapp/AndroidManifest.xml
index 576449b..8a9035e 100644
--- a/examples/androidapp/AndroidManifest.xml
+++ b/examples/androidapp/AndroidManifest.xml
@@ -8,7 +8,7 @@
     <uses-feature android:name="android.hardware.camera" />
     <uses-feature android:name="android.hardware.camera.autofocus" />
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
-    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="29" />
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
@@ -18,8 +18,6 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission tools:ignore="ProtectedPermissions"
-                     android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
 
     <!-- This is a test application that should always be debuggable. -->
     <application android:label="@string/app_name"
@@ -31,7 +29,8 @@
 
         <activity android:name="ConnectActivity"
                   android:label="@string/app_name"
-                  android:windowSoftInputMode="adjustPan">
+                  android:windowSoftInputMode="adjustPan"
+                  android:theme="@style/AppTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
@@ -47,7 +46,8 @@
         </activity>
 
         <activity android:name="SettingsActivity"
-                  android:label="@string/settings_name">
+                  android:label="@string/settings_name"
+                  android:theme="@style/AppTheme">
         </activity>
 
         <activity android:name="CallActivity"
diff --git a/examples/androidapp/res/layout/activity_connect.xml b/examples/androidapp/res/layout/activity_connect.xml
index 3c59189..017e5ca 100644
--- a/examples/androidapp/res/layout/activity_connect.xml
+++ b/examples/androidapp/res/layout/activity_connect.xml
@@ -24,7 +24,7 @@
 
         <!-- TODO(crbug.com/900912): Fix and remove lint ignore -->
         <EditText
-            tools:ignore="LabelFor"
+            tools:ignore="LabelFor,Autofill"
             android:id="@+id/room_edittext"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
diff --git a/examples/androidapp/res/values-v17/styles.xml b/examples/androidapp/res/values-v17/styles.xml
index 1d72850..969b501 100644
--- a/examples/androidapp/res/values-v17/styles.xml
+++ b/examples/androidapp/res/values-v17/styles.xml
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
+  <style name="AppTheme" parent="android:Theme.Holo" />
+
   <style name="CallActivityTheme" parent="android:Theme.Black">
     <item name="android:windowActionBar">false</item>
     <item name="android:windowFullscreen">true</item>
diff --git a/examples/androidapp/res/values-v21/styles.xml b/examples/androidapp/res/values-v21/styles.xml
index a051a23..b19af7e 100644
--- a/examples/androidapp/res/values-v21/styles.xml
+++ b/examples/androidapp/res/values-v21/styles.xml
@@ -1,8 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-  <style name="AppRTCMobileActivityTheme" parent="android:Theme.Material">
-    <item name="android:windowActionBar">false</item>
-    <item name="android:windowFullscreen">true</item>
-    <item name="android:windowNoTitle">true</item>
-  </style>
+  <style name="AppTheme" parent="android:Theme.Material" />
 </resources>
diff --git a/examples/androidapp/res/values/strings.xml b/examples/androidapp/res/values/strings.xml
index cd23356..814966f 100644
--- a/examples/androidapp/res/values/strings.xml
+++ b/examples/androidapp/res/values/strings.xml
@@ -27,6 +27,9 @@
     <string name="connect_description">Connect to the room</string>
     <string name="add_favorite_description">Add favorite</string>
     <string name="format_description">%1$dx%2$d @ %3$d fps</string>
+    <string name="missing_permissions_try_again">The application is missing permissions. It might not work correctly. Do you want to try again?</string>
+    <string name="yes">Yes</string>
+    <string name="no">No</string>
 
     <!-- Settings strings. -->
     <string name="pref_room_key">room_preference</string>
diff --git a/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java b/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java
index 87ceea6..2bd52cb 100644
--- a/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java
+++ b/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java
@@ -10,12 +10,17 @@
 
 package org.appspot.apprtc;
 
+import android.Manifest;
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.util.Log;
@@ -44,6 +49,7 @@
 public class ConnectActivity extends Activity {
   private static final String TAG = "ConnectActivity";
   private static final int CONNECTION_REQUEST = 1;
+  private static final int PERMISSION_REQUEST = 2;
   private static final int REMOVE_FAVORITE_INDEX = 0;
   private static boolean commandLineRun;
 
@@ -104,16 +110,7 @@
     addFavoriteButton = findViewById(R.id.add_favorite_button);
     addFavoriteButton.setOnClickListener(addFavoriteListener);
 
-    // If an implicit VIEW intent is launching the app, go directly to that URL.
-    final Intent intent = getIntent();
-    if ("android.intent.action.VIEW".equals(intent.getAction()) && !commandLineRun) {
-      boolean loopback = intent.getBooleanExtra(CallActivity.EXTRA_LOOPBACK, false);
-      int runTimeMs = intent.getIntExtra(CallActivity.EXTRA_RUNTIME, 0);
-      boolean useValuesFromIntent =
-          intent.getBooleanExtra(CallActivity.EXTRA_USE_VALUES_FROM_INTENT, false);
-      String room = sharedPref.getString(keyprefRoom, "");
-      connectToRoom(room, true, loopback, useValuesFromIntent, runTimeMs);
-    }
+    requestPermissions();
   }
 
   @Override
@@ -210,6 +207,95 @@
     }
   }
 
+  @Override
+  public void onRequestPermissionsResult(
+      int requestCode, String[] permissions, int[] grantResults) {
+    if (requestCode == PERMISSION_REQUEST) {
+      String[] missingPermissions = getMissingPermissions();
+      if (missingPermissions.length != 0) {
+        // User didn't grant all the permissions. Warn that the application might not work
+        // correctly.
+        new AlertDialog.Builder(this)
+            .setMessage(R.string.missing_permissions_try_again)
+            .setPositiveButton(R.string.yes,
+                (dialog, id) -> {
+                  // User wants to try giving the permissions again.
+                  dialog.cancel();
+                  requestPermissions();
+                })
+            .setNegativeButton(R.string.no,
+                (dialog, id) -> {
+                  // User doesn't want to give the permissions.
+                  dialog.cancel();
+                  onPermissionsGranted();
+                })
+            .show();
+      } else {
+        // All permissions granted.
+        onPermissionsGranted();
+      }
+    }
+  }
+
+  private void onPermissionsGranted() {
+    // If an implicit VIEW intent is launching the app, go directly to that URL.
+    final Intent intent = getIntent();
+    if ("android.intent.action.VIEW".equals(intent.getAction()) && !commandLineRun) {
+      boolean loopback = intent.getBooleanExtra(CallActivity.EXTRA_LOOPBACK, false);
+      int runTimeMs = intent.getIntExtra(CallActivity.EXTRA_RUNTIME, 0);
+      boolean useValuesFromIntent =
+          intent.getBooleanExtra(CallActivity.EXTRA_USE_VALUES_FROM_INTENT, false);
+      String room = sharedPref.getString(keyprefRoom, "");
+      connectToRoom(room, true, loopback, useValuesFromIntent, runTimeMs);
+    }
+  }
+
+  @TargetApi(Build.VERSION_CODES.M)
+  private void requestPermissions() {
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+      // Dynamic permissions are not required before Android M.
+      onPermissionsGranted();
+      return;
+    }
+
+    String[] missingPermissions = getMissingPermissions();
+    if (missingPermissions.length != 0) {
+      requestPermissions(missingPermissions, PERMISSION_REQUEST);
+    } else {
+      onPermissionsGranted();
+    }
+  }
+
+  @TargetApi(Build.VERSION_CODES.M)
+  private String[] getMissingPermissions() {
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+      return new String[0];
+    }
+
+    PackageInfo info;
+    try {
+      info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_PERMISSIONS);
+    } catch (PackageManager.NameNotFoundException e) {
+      Log.w(TAG, "Failed to retrieve permissions.");
+      return new String[0];
+    }
+
+    if (info.requestedPermissions == null) {
+      Log.w(TAG, "No requested permissions.");
+      return new String[0];
+    }
+
+    ArrayList<String> missingPermissions = new ArrayList<>();
+    for (int i = 0; i < info.requestedPermissions.length; i++) {
+      if ((info.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) {
+        missingPermissions.add(info.requestedPermissions[i]);
+      }
+    }
+    Log.d(TAG, "Missing permissions: " + missingPermissions);
+
+    return missingPermissions.toArray(new String[missingPermissions.size()]);
+  }
+
   /**
    * Get a value from the shared preference or from the intent, if it does not
    * exist the default is used.