merge in lmp-release history after reset to 1b1d8b0c3f29b2520554602eb72c0e9456efa5ac
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore b/admin/AppRestrictionEnforcer/Application/.gitignore
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore
copy to admin/AppRestrictionEnforcer/Application/.gitignore
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt b/admin/AppRestrictionEnforcer/Application/proguard-project.txt
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt
copy to admin/AppRestrictionEnforcer/Application/proguard-project.txt
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/AndroidManifest.xml b/admin/AppRestrictionEnforcer/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c66b4b3
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.apprestrictionenforcer"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
+
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name=".EnableProfileActivity"
+ android:label="@string/app_name" />
+
+ <receiver
+ android:name=".EnforcerDeviceAdminReceiver"
+ android:description="@string/app_name"
+ android:label="@string/app_name"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data
+ android:name="android.app.device_admin"
+ android:resource="@xml/enforcer_device_admin_receiver"/>
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
+ </intent-filter>
+ </receiver>
+
+ </application>
+
+
+</manifest>
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/big_icon.png b/admin/AppRestrictionEnforcer/Application/src/main/big_icon.png
new file mode 100644
index 0000000..24d83d9
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/big_icon.png
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/AppRestrictionEnforcerFragment.java b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/AppRestrictionEnforcerFragment.java
new file mode 100644
index 0000000..6db54f6
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/AppRestrictionEnforcerFragment.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionenforcer;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.RestrictionEntry;
+import android.content.RestrictionsManager;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.List;
+
+/**
+ * This fragment provides UI and functionality to set restrictions on the AppRestrictionSchema
+ * sample.
+ */
+public class AppRestrictionEnforcerFragment extends Fragment implements View.OnClickListener,
+ CompoundButton.OnCheckedChangeListener {
+
+ /**
+ * Package name of the AppRestrictionSchema sample.
+ */
+ private static final String PACKAGE_NAME_APP_RESTRICTION_SCHEMA
+ = "com.example.android.apprestrictionschema";
+
+ /**
+ * Key for {@link SharedPreferences}
+ */
+ private static final String PREFS_KEY = "AppRestrictionEnforcerFragment";
+
+ /**
+ * Key for the boolean restriction in AppRestrictionSchema.
+ */
+ private static final String RESTRICTION_KEY_SAY_HELLO = "can_say_hello";
+
+ /**
+ * Default boolean value for "can_say_hello" restriction. The actual value is loaded in
+ * {@link #loadRestrictions(android.app.Activity)}.
+ */
+ private boolean mDefaultValueRestrictionSayHello;
+
+ // UI Components
+ private TextView mTextStatus;
+ private Button mButtonUnhide;
+ private Switch mSwitchSayHello;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_app_restriction_enforcer, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ mTextStatus = (TextView) view.findViewById(R.id.status);
+ mButtonUnhide = (Button) view.findViewById(R.id.unhide);
+ mSwitchSayHello = (Switch) view.findViewById(R.id.say_hello);
+ mButtonUnhide.setOnClickListener(this);
+ mSwitchSayHello.setOnCheckedChangeListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateUi(getActivity());
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.unhide: {
+ unhideApp(getActivity());
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ switch (compoundButton.getId()) {
+ case R.id.say_hello: {
+ allowSayHello(getActivity(), checked);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Updates the UI components according to the current status of AppRestrictionSchema and its
+ * restriction.
+ *
+ * @param activity The activity
+ */
+ private void updateUi(Activity activity) {
+ PackageManager packageManager = activity.getPackageManager();
+ try {
+ ApplicationInfo info = packageManager.getApplicationInfo(
+ PACKAGE_NAME_APP_RESTRICTION_SCHEMA, PackageManager.GET_UNINSTALLED_PACKAGES);
+ DevicePolicyManager devicePolicyManager =
+ (DevicePolicyManager) activity.getSystemService(Activity.DEVICE_POLICY_SERVICE);
+ if (0 < (info.flags & ApplicationInfo.FLAG_INSTALLED)) {
+ if (!devicePolicyManager.isApplicationHidden(
+ EnforcerDeviceAdminReceiver.getComponentName(activity),
+ PACKAGE_NAME_APP_RESTRICTION_SCHEMA)) {
+ // The app is ready
+ loadRestrictions(activity);
+ mTextStatus.setVisibility(View.GONE);
+ mButtonUnhide.setVisibility(View.GONE);
+ mSwitchSayHello.setVisibility(View.VISIBLE);
+ mSwitchSayHello.setOnCheckedChangeListener(null);
+ mSwitchSayHello.setChecked(canSayHello(activity));
+ mSwitchSayHello.setOnCheckedChangeListener(this);
+ } else {
+ // The app is installed but hidden in this profile
+ mTextStatus.setText(R.string.status_not_activated);
+ mTextStatus.setVisibility(View.VISIBLE);
+ mButtonUnhide.setVisibility(View.VISIBLE);
+ mSwitchSayHello.setVisibility(View.GONE);
+ }
+ } else {
+ // Need to reinstall the sample app
+ mTextStatus.setText(R.string.status_need_reinstall);
+ mTextStatus.setVisibility(View.VISIBLE);
+ mButtonUnhide.setVisibility(View.GONE);
+ mSwitchSayHello.setVisibility(View.GONE);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ mTextStatus.setText(R.string.status_not_installed);
+ mTextStatus.setVisibility(View.VISIBLE);
+ mButtonUnhide.setVisibility(View.GONE);
+ mSwitchSayHello.setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * Unhides the AppRestrictionSchema sample in case it is hidden in this profile.
+ *
+ * @param activity The activity
+ */
+ private void unhideApp(Activity activity) {
+ DevicePolicyManager devicePolicyManager =
+ (DevicePolicyManager) activity.getSystemService(Activity.DEVICE_POLICY_SERVICE);
+ devicePolicyManager.setApplicationHidden(
+ EnforcerDeviceAdminReceiver.getComponentName(activity),
+ PACKAGE_NAME_APP_RESTRICTION_SCHEMA, false);
+ Toast.makeText(activity, "Enabled the app", Toast.LENGTH_SHORT).show();
+ updateUi(activity);
+ }
+
+ /**
+ * Loads the restrictions for the AppRestrictionSchema sample. In this implementation, we just
+ * read the default value for the "can_say_hello" restriction.
+ *
+ * @param activity The activity
+ */
+ private void loadRestrictions(Activity activity) {
+ RestrictionsManager restrictionsManager =
+ (RestrictionsManager) activity.getSystemService(Context.RESTRICTIONS_SERVICE);
+ List<RestrictionEntry> restrictions =
+ restrictionsManager.getManifestRestrictions(PACKAGE_NAME_APP_RESTRICTION_SCHEMA);
+ for (RestrictionEntry restriction : restrictions) {
+ if (RESTRICTION_KEY_SAY_HELLO.equals(restriction.getKey())) {
+ mDefaultValueRestrictionSayHello = restriction.getSelectedState();
+ }
+ }
+ }
+
+ /**
+ * Returns whether the AppRestrictionSchema is currently allowed to say hello to its user. Note
+ * that a profile/device owner needs to remember each restriction value on its own.
+ *
+ * @param activity The activity
+ * @return True if the AppRestrictionSchema is allowed to say hello
+ */
+ private boolean canSayHello(Activity activity) {
+ SharedPreferences prefs = activity.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE);
+ return prefs.getBoolean(RESTRICTION_KEY_SAY_HELLO, mDefaultValueRestrictionSayHello);
+ }
+
+ /**
+ * Sets the value for the "cay_say_hello" restriction of AppRestrictionSchema.
+ *
+ * @param activity The activity
+ * @param allow The value to be set for the restriction.
+ */
+ private void allowSayHello(Activity activity, boolean allow) {
+ DevicePolicyManager devicePolicyManager
+ = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ Bundle restrictions = new Bundle();
+ restrictions.putBoolean(RESTRICTION_KEY_SAY_HELLO, allow);
+ devicePolicyManager.setApplicationRestrictions(
+ EnforcerDeviceAdminReceiver.getComponentName(activity),
+ PACKAGE_NAME_APP_RESTRICTION_SCHEMA, restrictions);
+ // The profile/device owner needs to remember the current state of restrictions on its own
+ activity.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean(RESTRICTION_KEY_SAY_HELLO, allow)
+ .apply();
+ Toast.makeText(activity, allow ? R.string.allowed : R.string.disallowed,
+ Toast.LENGTH_SHORT).show();
+ }
+
+}
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnableProfileActivity.java b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnableProfileActivity.java
new file mode 100644
index 0000000..323ee99
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnableProfileActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionenforcer;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This activity is started after the provisioning is complete in
+ * {@link EnforcerDeviceAdminReceiver}.
+ */
+public class EnableProfileActivity extends FragmentActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (null == savedInstanceState) {
+ // Enable the newly created profile
+ DevicePolicyManager manager =
+ (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+ ComponentName componentName = EnforcerDeviceAdminReceiver.getComponentName(this);
+ manager.setProfileName(componentName, getString(R.string.profile_name));
+ manager.setProfileEnabled(componentName);
+ }
+ // Open the main screen
+ startActivity(new Intent(this, MainActivity.class));
+ finish();
+ }
+
+}
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnforcerDeviceAdminReceiver.java b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnforcerDeviceAdminReceiver.java
new file mode 100644
index 0000000..09d9e98
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/EnforcerDeviceAdminReceiver.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionenforcer;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Handles events related to managed profile.
+ */
+public class EnforcerDeviceAdminReceiver extends DeviceAdminReceiver {
+
+ /**
+ * Called on the new profile when managed profile provisioning has completed. Managed profile
+ * provisioning is the process of setting up the device so that it has a separate profile which
+ * is managed by the mobile device management(mdm) application that triggered the provisioning.
+ * Note that the managed profile is not fully visible until it is enabled.
+ */
+ @Override
+ public void onProfileProvisioningComplete(Context context, Intent intent) {
+ // EnableProfileActivity is launched with the newly set up profile.
+ Intent launch = new Intent(context, EnableProfileActivity.class);
+ launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(launch);
+ }
+
+ /**
+ * Generates a {@link ComponentName} that is used throughout the app.
+ * @return a {@link ComponentName}
+ */
+ public static ComponentName getComponentName(Context context) {
+ return new ComponentName(context.getApplicationContext(),
+ EnforcerDeviceAdminReceiver.class);
+ }
+
+}
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/MainActivity.java b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/MainActivity.java
new file mode 100644
index 0000000..72224e1
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/MainActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionenforcer;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+public class MainActivity extends FragmentActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main_real);
+ if (null == savedInstanceState) {
+ DevicePolicyManager manager = (DevicePolicyManager)
+ getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (manager.isProfileOwnerApp(getApplicationContext().getPackageName())) {
+ // If the managed profile is already set up, we show the main screen.
+ showMainFragment();
+ } else {
+ // If not, we show the set up screen.
+ showSetupProfile();
+ }
+ }
+ }
+
+ private void showSetupProfile() {
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.container, new SetupProfileFragment())
+ .commit();
+ }
+
+ private void showMainFragment() {
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.container, new AppRestrictionEnforcerFragment())
+ .commit();
+ }
+
+}
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/SetupProfileFragment.java b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/SetupProfileFragment.java
new file mode 100644
index 0000000..4dbd930
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/java/com/example/android/apprestrictionenforcer/SetupProfileFragment.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionenforcer;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_DEVICE_ADMIN;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+
+/**
+ * This {@link Fragment} handles initiation of managed profile provisioning.
+ */
+public class SetupProfileFragment extends Fragment implements View.OnClickListener {
+
+ private static final int REQUEST_PROVISION_MANAGED_PROFILE = 1;
+
+ public static SetupProfileFragment newInstance() {
+ return new SetupProfileFragment();
+ }
+
+ public SetupProfileFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_setup_profile, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ view.findViewById(R.id.set_up_profile).setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.set_up_profile: {
+ provisionManagedProfile();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Initiates the managed profile provisioning. If we already have a managed profile set up on
+ * this device, we will get an error dialog in the following provisioning phase.
+ */
+ private void provisionManagedProfile() {
+ Activity activity = getActivity();
+ if (null == activity) {
+ return;
+ }
+ Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
+ activity.getApplicationContext().getPackageName());
+ intent.putExtra(EXTRA_DEVICE_ADMIN, EnforcerDeviceAdminReceiver.getComponentName(activity));
+ if (intent.resolveActivity(activity.getPackageManager()) != null) {
+ startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
+ activity.finish();
+ } else {
+ Toast.makeText(activity, "Device provisioning is not enabled. Stopping.",
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_PROVISION_MANAGED_PROFILE) {
+ if (resultCode == Activity.RESULT_OK) {
+ Toast.makeText(getActivity(), "Provisioning done.", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getActivity(), "Provisioning failed.", Toast.LENGTH_SHORT).show();
+ }
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+}
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-hdpi/ic_launcher.png b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..e7bd161
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-mdpi/ic_launcher.png b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4c42c9c
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..3ec3368
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..730f80c
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/layout/activity_main_real.xml b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/activity_main_real.xml
new file mode 100644
index 0000000..d36c2b6
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/activity_main_real.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/vertical_page_margin"
+ android:layout_marginLeft="@dimen/horizontal_page_margin"
+ android:layout_marginRight="@dimen/horizontal_page_margin"
+ android:layout_marginTop="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_app_restriction_enforcer.xml b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_app_restriction_enforcer.xml
new file mode 100644
index 0000000..e6c50a2
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_app_restriction_enforcer.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin">
+
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/status_not_installed" />
+
+ <Button
+ android:id="@+id/unhide"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/unhide" />
+
+ <Switch
+ android:id="@+id/say_hello"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/allow_saying_hello" />
+
+</LinearLayout>
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_setup_profile.xml b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_setup_profile.xml
new file mode 100644
index 0000000..e9e9fe8
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/layout/fragment_setup_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.example.android.basicmanagedprofile.MainActivity.MainFragment">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/setup_profile_message" />
+
+ <Button
+ android:id="@+id/set_up_profile"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set_up_profile" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/values/strings.xml b/admin/AppRestrictionEnforcer/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3029e04
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 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.
+-->
+<resources>
+ <string name="setup_profile_message">This app is currently not a profile owner.</string>
+ <string name="set_up_profile">Set up profile</string>
+ <string name="status_not_installed">AppRestrictionsSchema is not installed.</string>
+ <string name="status_not_activated">AppRestrictionsSchema is installed, but not activated in this profile.</string>
+ <string name="status_need_reinstall">AppRestrictionSchema needs reinstalling.</string>
+ <string name="unhide">Activate AppRestrictionSchema</string>
+ <string name="allow_saying_hello">Allow AppRestrictionSchema to say hello: </string>
+ <string name="allowed">Allowed</string>
+ <string name="disallowed">Disallowed</string>
+ <string name="profile_name">AppRestrictionEnforcer </string>
+</resources>
diff --git a/admin/AppRestrictionEnforcer/Application/src/main/res/xml/enforcer_device_admin_receiver.xml b/admin/AppRestrictionEnforcer/Application/src/main/res/xml/enforcer_device_admin_receiver.xml
new file mode 100644
index 0000000..5e084c6
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/src/main/res/xml/enforcer_device_admin_receiver.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 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.
+-->
+<device-admin>
+ <uses-policies>
+ <limit-password />
+ <watch-login />
+ <reset-password />
+ <force-lock />
+ <wipe-data />
+ <expire-password />
+ <encrypted-storage />
+ </uses-policies>
+</device-admin>
diff --git a/admin/AppRestrictionEnforcer/Application/tests/src/com/example/android/apprestrictionenforcer/tests/SampleTests.java b/admin/AppRestrictionEnforcer/Application/tests/src/com/example/android/apprestrictionenforcer/tests/SampleTests.java
new file mode 100644
index 0000000..fbed64a
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/Application/tests/src/com/example/android/apprestrictionenforcer/tests/SampleTests.java
@@ -0,0 +1,79 @@
+/*
+* Copyright 2013 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.
+*/
+
+
+
+/*
+* Copyright (C) 2013 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.example.android.apprestrictionenforcer.tests;
+
+import com.example.android.apprestrictionenforcer.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for AppRestrictionEnforcer sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<MainActivity> {
+
+ private MainActivity mTestActivity;
+ private AppRestrictionEnforcerFragment mTestFragment;
+
+ public SampleTests() {
+ super(MainActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Starts the activity under test using the default Intent with:
+ // action = {@link Intent#ACTION_MAIN}
+ // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+ // All other fields are null or empty.
+ mTestActivity = getActivity();
+ mTestFragment = (AppRestrictionEnforcerFragment)
+ mTestActivity.getSupportFragmentManager().getFragments().get(1);
+ }
+
+ /**
+ * Test if the test fixture has been set up correctly.
+ */
+ public void testPreconditions() {
+ //Try to add a message to add context to your assertions. These messages will be shown if
+ //a tests fails and make it easy to understand why a test failed
+ assertNotNull("mTestActivity is null", mTestActivity);
+ assertNotNull("mTestFragment is null", mTestFragment);
+ }
+
+ /**
+ * Add more tests below.
+ */
+
+}
\ No newline at end of file
diff --git a/admin/AppRestrictionEnforcer/CONTRIB.md b/admin/AppRestrictionEnforcer/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/admin/AppRestrictionEnforcer/LICENSE b/admin/AppRestrictionEnforcer/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 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.
diff --git a/admin/AppRestrictionEnforcer/build.gradle b/admin/AppRestrictionEnforcer/build.gradle
new file mode 100644
index 0000000..f9f6f65
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../build"
+ pathToSamplesCommon "../../common"
+}
+apply from: "../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/admin/AppRestrictionEnforcer/buildSrc/build.gradle b/admin/AppRestrictionEnforcer/buildSrc/build.gradle
new file mode 100644
index 0000000..29282af
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar b/admin/AppRestrictionEnforcer/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar
copy to admin/AppRestrictionEnforcer/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/admin/AppRestrictionEnforcer/gradle/wrapper/gradle-wrapper.properties b/admin/AppRestrictionEnforcer/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew b/admin/AppRestrictionEnforcer/gradlew
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew
copy to admin/AppRestrictionEnforcer/gradlew
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew.bat b/admin/AppRestrictionEnforcer/gradlew.bat
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew.bat
copy to admin/AppRestrictionEnforcer/gradlew.bat
diff --git a/admin/AppRestrictionEnforcer/settings.gradle b/admin/AppRestrictionEnforcer/settings.gradle
new file mode 100644
index 0000000..9464a35
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/settings.gradle
@@ -0,0 +1 @@
+include 'Application'
diff --git a/admin/AppRestrictionEnforcer/template-params.xml b/admin/AppRestrictionEnforcer/template-params.xml
new file mode 100644
index 0000000..ff1a7a0
--- /dev/null
+++ b/admin/AppRestrictionEnforcer/template-params.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+
+
+<sample>
+ <name>AppRestrictionEnforcer</name>
+ <group>Admin</group>
+ <package>com.example.android.apprestrictionenforcer</package>
+
+ <minSdk>21</minSdk>
+ <compileSdkVersion>21</compileSdkVersion>
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample demonstrates how to set restrictions to other apps as a profile owner.
+ Use AppRestrictionSchema sample as a app with available restrictions.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base" />
+</sample>
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore b/admin/AppRestrictionSchema/Application/.gitignore
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore
copy to admin/AppRestrictionSchema/Application/.gitignore
diff --git a/admin/AppRestrictionSchema/Application/README-fragmentview.txt b/admin/AppRestrictionSchema/Application/README-fragmentview.txt
new file mode 100644
index 0000000..38d903f
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/README-fragmentview.txt
@@ -0,0 +1,37 @@
+<!--
+ Copyright 2013 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.
+-->
+
+Steps to implement FragmentView template:
+-in template-params.xml.ftl:
+ -add the following line to common imports
+ <common src="activities"/>
+
+-Add a Fragment to show behavior. In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java. Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+ For instance, if your package name is com.example.foo, create the file
+ src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/fragmentViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt b/admin/AppRestrictionSchema/Application/proguard-project.txt
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt
copy to admin/AppRestrictionSchema/Application/proguard-project.txt
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml b/admin/AppRestrictionSchema/Application/src/main/AndroidManifest.xml
similarity index 69%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml
copy to admin/AppRestrictionSchema/Application/src/main/AndroidManifest.xml
index 71ac7d0..f8bbccc 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml
+++ b/admin/AppRestrictionSchema/Application/src/main/AndroidManifest.xml
@@ -16,29 +16,31 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.documentcentricrecents"
+ package="com.example.android.apprestrictionschema"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="android-L" android:targetSdkVersion="android-L" />
+ <!-- uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" /-->
- <application android:allowBackup="true"
- android:label="@string/app_name"
+ <application
+ android:allowBackup="true"
android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
android:theme="@style/AppTheme">
- <activity android:name=".DocumentCentricActivity"
- android:label="@string/app_name"
- android:persistableMode="persistAcrossReboots">
+ <meta-data
+ android:name="android.content.APP_RESTRICTIONS"
+ android:resource="@xml/app_restrictions" />
+
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity
- android:name=".NewDocumentActivity"
- android:label="@string/activity_new_document_title" >
- </activity>
</application>
+
</manifest>
diff --git a/admin/AppRestrictionSchema/Application/src/main/big_icon.png b/admin/AppRestrictionSchema/Application/src/main/big_icon.png
new file mode 100644
index 0000000..2115454
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/big_icon.png
Binary files differ
diff --git a/admin/AppRestrictionSchema/Application/src/main/java/com/example/android/apprestrictionschema/AppRestrictionSchemaFragment.java b/admin/AppRestrictionSchema/Application/src/main/java/com/example/android/apprestrictionschema/AppRestrictionSchemaFragment.java
new file mode 100644
index 0000000..76f024f
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/java/com/example/android/apprestrictionschema/AppRestrictionSchemaFragment.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 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.example.android.apprestrictionschema;
+
+import android.content.Context;
+import android.content.RestrictionsManager;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.android.common.logger.Log;
+
+/**
+ * Pressing the button on this fragment pops up a simple Toast message. The button is enabled or
+ * disabled according to the restrictions set by device/profile owner. You can use the
+ * AppRestrictionEnforcer sample as a profile owner for this.
+ */
+public class AppRestrictionSchemaFragment extends Fragment implements View.OnClickListener {
+
+ // Tag for the logger
+ private static final String TAG = "AppRestrictionSchemaFragment";
+
+ // UI Components
+ private TextView mTextSayHello;
+ private Button mButtonSayHello;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_app_restriction_schema, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ mTextSayHello = (TextView) view.findViewById(R.id.say_hello_explanation);
+ mButtonSayHello = (Button) view.findViewById(R.id.say_hello);
+ mButtonSayHello.setOnClickListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Update the UI according to the configured restrictions
+ RestrictionsManager restrictionsManager =
+ (RestrictionsManager) getActivity().getSystemService(Context.RESTRICTIONS_SERVICE);
+ Bundle restrictions = restrictionsManager.getApplicationRestrictions();
+ updateUI(restrictions);
+ }
+
+ private void updateUI(Bundle restrictions) {
+ if (canSayHello(restrictions)) {
+ mTextSayHello.setText(R.string.explanation_can_say_hello_true);
+ mButtonSayHello.setEnabled(true);
+ } else {
+ mTextSayHello.setText(R.string.explanation_can_say_hello_false);
+ mButtonSayHello.setEnabled(false);
+ }
+ }
+
+ /**
+ * Returns the current status of the restriction.
+ *
+ * @param restrictions The application restrictions
+ * @return True if the app is allowed to say hello
+ */
+ private boolean canSayHello(Bundle restrictions) {
+ final boolean defaultValue = false;
+ boolean canSayHello = restrictions == null ? defaultValue :
+ restrictions.getBoolean("can_say_hello", defaultValue);
+ Log.d(TAG, "canSayHello: " + canSayHello);
+ return canSayHello;
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.say_hello: {
+ Toast.makeText(getActivity(), R.string.message_hello, Toast.LENGTH_SHORT).show();
+ break;
+ }
+ }
+ }
+
+}
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/drawable-hdpi/ic_launcher.png b/admin/AppRestrictionSchema/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..74344d7
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/drawable-mdpi/ic_launcher.png b/admin/AppRestrictionSchema/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a01dbd7
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/admin/AppRestrictionSchema/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..19bb139
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/admin/AppRestrictionSchema/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..9922ae6
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/layout/activity_main_real.xml b/admin/AppRestrictionSchema/Application/src/main/res/layout/activity_main_real.xml
new file mode 100644
index 0000000..8aa1c8b
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/layout/activity_main_real.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2014 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <FrameLayout style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/horizontal_page_margin"
+ android:layout_marginRight="@dimen/horizontal_page_margin"
+ android:layout_marginTop="@dimen/vertical_page_margin"
+ android:layout_marginBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/layout/fragment_app_restriction_schema.xml b/admin/AppRestrictionSchema/Application/src/main/res/layout/fragment_app_restriction_schema.xml
new file mode 100644
index 0000000..fc5e23d
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/layout/fragment_app_restriction_schema.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2014 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="@dimen/margin_medium">
+
+ <TextView
+ android:id="@+id/say_hello_explanation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/explanation_can_say_hello_true"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <Button
+ android:id="@+id/say_hello"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/margin_medium"
+ android:text="@string/action_can_say_hello" />
+
+</LinearLayout>
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/values/strings.xml b/admin/AppRestrictionSchema/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b8ef110
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/values/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2014 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.
+-->
+<resources>
+
+ <string name="title_can_say_hello">Can say hello</string>
+ <string name="description_can_say_hello">Whether the app can say hello to the user</string>
+ <string name="explanation_can_say_hello_true">I can say hello to you.</string>
+ <string name="explanation_can_say_hello_false">I am restricted from saying hello to you.</string>
+ <string name="action_can_say_hello">Say hello</string>
+ <string name="message_hello">Hello!</string>
+
+</resources>
\ No newline at end of file
diff --git a/admin/AppRestrictionSchema/Application/src/main/res/xml/app_restrictions.xml b/admin/AppRestrictionSchema/Application/src/main/res/xml/app_restrictions.xml
new file mode 100644
index 0000000..409527f
--- /dev/null
+++ b/admin/AppRestrictionSchema/Application/src/main/res/xml/app_restrictions.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2014 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.
+-->
+<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <restriction
+ android:defaultValue="false"
+ android:description="@string/description_can_say_hello"
+ android:key="can_say_hello"
+ android:restrictionType="bool"
+ android:title="@string/title_can_say_hello" />
+
+</restrictions>
diff --git a/admin/AppRestrictionSchema/CONTRIB.md b/admin/AppRestrictionSchema/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/admin/AppRestrictionSchema/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/admin/AppRestrictionSchema/LICENSE b/admin/AppRestrictionSchema/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/admin/AppRestrictionSchema/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 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.
diff --git a/admin/AppRestrictionSchema/build.gradle b/admin/AppRestrictionSchema/build.gradle
new file mode 100644
index 0000000..f9f6f65
--- /dev/null
+++ b/admin/AppRestrictionSchema/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../build"
+ pathToSamplesCommon "../../common"
+}
+apply from: "../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/admin/AppRestrictionSchema/buildSrc/build.gradle b/admin/AppRestrictionSchema/buildSrc/build.gradle
new file mode 100644
index 0000000..29282af
--- /dev/null
+++ b/admin/AppRestrictionSchema/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar b/admin/AppRestrictionSchema/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar
copy to admin/AppRestrictionSchema/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/admin/AppRestrictionSchema/gradle/wrapper/gradle-wrapper.properties b/admin/AppRestrictionSchema/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/admin/AppRestrictionSchema/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew b/admin/AppRestrictionSchema/gradlew
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew
copy to admin/AppRestrictionSchema/gradlew
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew.bat b/admin/AppRestrictionSchema/gradlew.bat
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew.bat
copy to admin/AppRestrictionSchema/gradlew.bat
diff --git a/admin/AppRestrictionSchema/settings.gradle b/admin/AppRestrictionSchema/settings.gradle
new file mode 100644
index 0000000..9464a35
--- /dev/null
+++ b/admin/AppRestrictionSchema/settings.gradle
@@ -0,0 +1 @@
+include 'Application'
diff --git a/admin/AppRestrictionSchema/template-params.xml b/admin/AppRestrictionSchema/template-params.xml
new file mode 100644
index 0000000..c6ec4a1
--- /dev/null
+++ b/admin/AppRestrictionSchema/template-params.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 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.
+-->
+
+<sample>
+ <name>AppRestrictionSchema</name>
+ <group>Admin</group>
+ <package>com.example.android.apprestrictionschema</package>
+
+ <minSdk>21</minSdk>
+ <compileSdkVersion>21</compileSdkVersion>
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample shows how to use app restrictions. This application has one boolean
+ restriction with a key \"can_say_hello\" that defines whether the only feature of this
+ app (press the button to show \"Hello\" message) is enabled or disabled. Use
+ AppRestrictionEnforcer sample to toggle the restriction.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base" />
+ <template src="FragmentView" />
+ <common src="logger" />
+ <common src="activities" />
+
+</sample>
diff --git a/admin/BasicManagedProfile/Application/src/main/AndroidManifest.xml b/admin/BasicManagedProfile/Application/src/main/AndroidManifest.xml
index 6ba2361..29020c3 100644
--- a/admin/BasicManagedProfile/Application/src/main/AndroidManifest.xml
+++ b/admin/BasicManagedProfile/Application/src/main/AndroidManifest.xml
@@ -15,16 +15,20 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+<manifest
package="com.example.android.basicmanagedprofile"
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+ <uses-sdk
+ android:minSdkVersion="21"
+ android:targetSdkVersion="21"/>
<application
+ android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
- android:icon="@drawable/ic_launcher">
+ android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
diff --git a/admin/BasicManagedProfile/Application/src/main/java/com/example/android/basicmanagedprofile/BasicManagedProfileFragment.java b/admin/BasicManagedProfile/Application/src/main/java/com/example/android/basicmanagedprofile/BasicManagedProfileFragment.java
index bb3f239..beb8d4a 100644
--- a/admin/BasicManagedProfile/Application/src/main/java/com/example/android/basicmanagedprofile/BasicManagedProfileFragment.java
+++ b/admin/BasicManagedProfile/Application/src/main/java/com/example/android/basicmanagedprofile/BasicManagedProfileFragment.java
@@ -133,6 +133,7 @@
public void onViewCreated(View view, Bundle savedInstanceState) {
// Bind event listeners and initial states
view.findViewById(R.id.set_chrome_restrictions).setOnClickListener(this);
+ view.findViewById(R.id.clear_chrome_restrictions).setOnClickListener(this);
view.findViewById(R.id.enable_forwarding).setOnClickListener(this);
view.findViewById(R.id.disable_forwarding).setOnClickListener(this);
view.findViewById(R.id.send_intent).setOnClickListener(this);
@@ -153,6 +154,10 @@
setChromeRestrictions();
break;
}
+ case R.id.clear_chrome_restrictions: {
+ clearChromeRestrictions();
+ break;
+ }
case R.id.enable_forwarding: {
enableForwarding();
break;
@@ -285,6 +290,24 @@
}
/**
+ * Clears restrictions to Chrome
+ */
+ private void clearChromeRestrictions() {
+ final Activity activity = getActivity();
+ if (null == activity) {
+ return;
+ }
+ final DevicePolicyManager manager =
+ (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ // In order to clear restrictions, pass null as the restriction Bundle for
+ // setApplicationRestrictions
+ manager.setApplicationRestrictions
+ (BasicDeviceAdminReceiver.getComponentName(activity),
+ PACKAGE_NAME_CHROME, null);
+ Toast.makeText(activity, R.string.cleared, Toast.LENGTH_SHORT).show();
+ }
+
+ /**
* Enables forwarding of share intent between private account and managed profile.
*/
private void enableForwarding() {
diff --git a/admin/BasicManagedProfile/Application/src/main/res/layout/fragment_main.xml b/admin/BasicManagedProfile/Application/src/main/res/layout/fragment_main.xml
index 7dcb9f2..a5ba580 100644
--- a/admin/BasicManagedProfile/Application/src/main/res/layout/fragment_main.xml
+++ b/admin/BasicManagedProfile/Application/src/main/res/layout/fragment_main.xml
@@ -60,6 +60,12 @@
android:layout_height="wrap_content"
android:text="@string/set_chrome_restrictions" />
+ <Button
+ android:id="@+id/clear_chrome_restrictions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/clear_chrome_restrictions" />
+
<!-- Intent Forwarding -->
<Button
diff --git a/admin/BasicManagedProfile/Application/src/main/res/values/strings.xml b/admin/BasicManagedProfile/Application/src/main/res/values/strings.xml
index 3e9f8fa..240c7ab 100644
--- a/admin/BasicManagedProfile/Application/src/main/res/values/strings.xml
+++ b/admin/BasicManagedProfile/Application/src/main/res/values/strings.xml
@@ -28,11 +28,13 @@
<string name="toggle_calculator">Calculator in this profile: </string>
<string name="toggle_chrome">Chrome in this profile:</string>
<string name="set_chrome_restrictions">Set Chrome restrictions</string>
+ <string name="clear_chrome_restrictions">Clear Chrome restrictions</string>
<string name="icon">Icon</string>
<string name="profile_name">Sample Managed Profile</string>
<string name="enabled">Enabled</string>
<string name="disabled">Disabled</string>
<string name="restrictions_set">Restrictions set.</string>
<string name="activity_not_found">No app can handle this intent.</string>
+ <string name="cleared">Cleared.</string>
</resources>
diff --git a/background/alarms/RepeatingAlarm/Application/src/main/AndroidManifest.xml b/background/alarms/RepeatingAlarm/Application/src/main/AndroidManifest.xml
index b7d02e5..0fbdc7a 100644
--- a/background/alarms/RepeatingAlarm/Application/src/main/AndroidManifest.xml
+++ b/background/alarms/RepeatingAlarm/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/build.gradle b/build.gradle
index 34fd249..1f23be0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -48,6 +48,7 @@
"ui/views/SwipeRefreshLayout/SwipeRefreshListFragment",
"ui/views/SwipeRefreshLayout/SwipeRefreshMultipleViews",
"media/MediaRouter",
+"media/MediaEffects",
"admin/BasicManagedProfile",
"media/Camera2Basic",
"media/Camera2Video",
@@ -65,6 +66,12 @@
"ui/notifications/LNotifications",
"ui/DrawableTinting",
"ui/Interpolator",
+"media/HdrViewfinder",
+"ui/activitytasks/DocumentCentricApps",
+"ui/activitytasks/DocumentCentricRelinquishIdentity",
+"admin/AppRestrictionEnforcer",
+"admin/AppRestrictionSchema",
+"bluetooth/BluetoothChat",
]
List<String> taskNames = [
diff --git a/connectivity/bluetooth/BluetoothLeGatt/Application/src/main/AndroidManifest.xml b/connectivity/bluetooth/BluetoothLeGatt/Application/src/main/AndroidManifest.xml
index babd6df..d3cf257 100644
--- a/connectivity/bluetooth/BluetoothLeGatt/Application/src/main/AndroidManifest.xml
+++ b/connectivity/bluetooth/BluetoothLeGatt/Application/src/main/AndroidManifest.xml
@@ -22,8 +22,8 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="18"
- android:targetSdkVersion="18"/>
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
+
<!-- Declare this required feature if you want to make the app available to BLE-capable
devices only. If you want to make your app available to devices that don't support BLE,
you should omit this in the manifest. Instead, determine BLE capability by using
diff --git a/connectivity/network/BasicNetworking/Application/src/main/AndroidManifest.xml b/connectivity/network/BasicNetworking/Application/src/main/AndroidManifest.xml
index 48bfeac..b512790 100644
--- a/connectivity/network/BasicNetworking/Application/src/main/AndroidManifest.xml
+++ b/connectivity/network/BasicNetworking/Application/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/connectivity/network/NetworkConnect/Application/src/main/AndroidManifest.xml b/connectivity/network/NetworkConnect/Application/src/main/AndroidManifest.xml
index 1ae29df..00ce7f3 100644
--- a/connectivity/network/NetworkConnect/Application/src/main/AndroidManifest.xml
+++ b/connectivity/network/NetworkConnect/Application/src/main/AndroidManifest.xml
@@ -23,7 +23,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/connectivity/nfc/BeamLargeFiles/Application/src/main/AndroidManifest.xml b/connectivity/nfc/BeamLargeFiles/Application/src/main/AndroidManifest.xml
index cda0866..6ef958d 100644
--- a/connectivity/nfc/BeamLargeFiles/Application/src/main/AndroidManifest.xml
+++ b/connectivity/nfc/BeamLargeFiles/Application/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
android:versionName="1.0">
<!-- Large file beam requires API 16 or above. -->
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<!-- The NFC permission is required to use NfcAdapter. -->
<uses-permission android:name="android.permission.NFC" />
diff --git a/connectivity/nfc/CardEmulation/Application/src/main/AndroidManifest.xml b/connectivity/nfc/CardEmulation/Application/src/main/AndroidManifest.xml
index 4a4af08..fba9a74 100644
--- a/connectivity/nfc/CardEmulation/Application/src/main/AndroidManifest.xml
+++ b/connectivity/nfc/CardEmulation/Application/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
android:versionName="1.0">
<!-- Card emulation was introduced in API 19. -->
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
<uses-permission android:name="android.permission.NFC" />
diff --git a/connectivity/nfc/CardReader/Application/src/main/AndroidManifest.xml b/connectivity/nfc/CardReader/Application/src/main/AndroidManifest.xml
index a8ebd13..ed25c6f 100644
--- a/connectivity/nfc/CardReader/Application/src/main/AndroidManifest.xml
+++ b/connectivity/nfc/CardReader/Application/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
android:versionName="1.0">
<!-- NFC Reader Mode was added in API 19. -->
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
diff --git a/content/documentsUi/StorageClient/Application/src/main/AndroidManifest.xml b/content/documentsUi/StorageClient/Application/src/main/AndroidManifest.xml
index d35a4ec..0bcfde9 100644
--- a/content/documentsUi/StorageClient/Application/src/main/AndroidManifest.xml
+++ b/content/documentsUi/StorageClient/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/content/multiuser/AppRestrictions/Application/src/main/AndroidManifest.xml b/content/multiuser/AppRestrictions/Application/src/main/AndroidManifest.xml
index b492bbf..ddac9cf 100644
--- a/content/multiuser/AppRestrictions/Application/src/main/AndroidManifest.xml
+++ b/content/multiuser/AppRestrictions/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="18" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
diff --git a/input/gestures/BasicGestureDetect/Application/src/main/AndroidManifest.xml b/input/gestures/BasicGestureDetect/Application/src/main/AndroidManifest.xml
index 87ed603..aaa4f41 100644
--- a/input/gestures/BasicGestureDetect/Application/src/main/AndroidManifest.xml
+++ b/input/gestures/BasicGestureDetect/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="13" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/media/BasicMediaDecoder/Application/src/main/AndroidManifest.xml b/media/BasicMediaDecoder/Application/src/main/AndroidManifest.xml
index d191491..02a674e 100644
--- a/media/BasicMediaDecoder/Application/src/main/AndroidManifest.xml
+++ b/media/BasicMediaDecoder/Application/src/main/AndroidManifest.xml
@@ -20,7 +20,8 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="17"/>
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
+
<application
android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity
diff --git a/media/Camera2Basic/Application/src/main/AndroidManifest.xml b/media/Camera2Basic/Application/src/main/AndroidManifest.xml
index 66cdbac..87d9af1 100644
--- a/media/Camera2Basic/Application/src/main/AndroidManifest.xml
+++ b/media/Camera2Basic/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.CAMERA" />
<application android:allowBackup="true"
diff --git a/media/Camera2Basic/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java b/media/Camera2Basic/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java
index a97da80..f4bf220 100644
--- a/media/Camera2Basic/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java
+++ b/media/Camera2Basic/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java
@@ -63,6 +63,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
public class Camera2BasicFragment extends Fragment implements View.OnClickListener {
@@ -167,18 +169,21 @@
@Override
public void onOpened(CameraDevice cameraDevice) {
// This method is called when the camera is opened. We start camera preview here.
+ mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
+ mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
+ mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
Activity activity = getActivity();
@@ -241,6 +246,11 @@
private int mState = STATE_PREVIEW;
/**
+ * A {@link Semaphore} to prevent the app from exiting before closing the camera.
+ */
+ private Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+ /**
* A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
*/
private CameraCaptureSession.CaptureCallback mCaptureCallback
@@ -449,9 +459,14 @@
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock camera opening.");
+ }
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
}
}
@@ -459,17 +474,24 @@
* Closes the current {@link CameraDevice}.
*/
private void closeCamera() {
- if (null != mCaptureSession) {
- mCaptureSession.close();
- mCaptureSession = null;
- }
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
- if (null != mImageReader) {
- mImageReader.close();
- mImageReader = null;
+ try {
+ mCameraOpenCloseLock.acquire();
+ if (null != mCaptureSession) {
+ mCaptureSession.close();
+ mCaptureSession = null;
+ }
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mImageReader) {
+ mImageReader.close();
+ mImageReader = null;
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
+ } finally {
+ mCameraOpenCloseLock.release();
}
}
@@ -521,6 +543,11 @@
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
+ // The camera is already closed
+ if (null == mCameraDevice) {
+ return;
+ }
+
// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession;
try {
diff --git a/media/Camera2Video/Application/src/main/AndroidManifest.xml b/media/Camera2Video/Application/src/main/AndroidManifest.xml
index 330c15b..5cb5428 100644
--- a/media/Camera2Video/Application/src/main/AndroidManifest.xml
+++ b/media/Camera2Video/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
diff --git a/media/Camera2Video/Application/src/main/java/com/example/android/camera2video/Camera2VideoFragment.java b/media/Camera2Video/Application/src/main/java/com/example/android/camera2video/Camera2VideoFragment.java
index 903dd18..78e276a 100644
--- a/media/Camera2Video/Application/src/main/java/com/example/android/camera2video/Camera2VideoFragment.java
+++ b/media/Camera2Video/Application/src/main/java/com/example/android/camera2video/Camera2VideoFragment.java
@@ -39,6 +39,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
+import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
@@ -52,13 +53,18 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
public class Camera2VideoFragment extends Fragment implements View.OnClickListener {
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+ private static final String TAG = "Camera2VideoFragment";
+
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
@@ -96,15 +102,13 @@
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
int width, int height) {
- configureTransform(width, height);
- startPreview();
+ openCamera(width, height);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
int width, int height) {
configureTransform(width, height);
- startPreview();
}
@Override
@@ -124,6 +128,11 @@
private Size mPreviewSize;
/**
+ * The {@link android.util.Size} of video recording.
+ */
+ private Size mVideoSize;
+
+ /**
* Camera preview.
*/
private CaptureRequest.Builder mPreviewBuilder;
@@ -139,9 +148,19 @@
private boolean mIsRecordingVideo;
/**
- * Whether the app is currently trying to open camera
+ * An additional thread for running tasks that shouldn't block the UI.
*/
- private boolean mOpeningCamera;
+ private HandlerThread mBackgroundThread;
+
+ /**
+ * A {@link Handler} for running tasks in the background.
+ */
+ private Handler mBackgroundHandler;
+
+ /**
+ * A {@link Semaphore} to prevent the app from exiting before closing the camera.
+ */
+ private Semaphore mCameraOpenCloseLock = new Semaphore(1);
/**
* {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its status.
@@ -152,7 +171,7 @@
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
startPreview();
- mOpeningCamera = false;
+ mCameraOpenCloseLock.release();
if (null != mTextureView) {
configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
}
@@ -160,20 +179,20 @@
@Override
public void onDisconnected(CameraDevice cameraDevice) {
+ mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
- mOpeningCamera = false;
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
+ mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
Activity activity = getActivity();
if (null != activity) {
activity.finish();
}
- mOpeningCamera = false;
}
};
@@ -184,6 +203,55 @@
return fragment;
}
+ /**
+ * In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes larger
+ * than 1080p, since MediaRecorder cannot handle such a high-resolution video.
+ *
+ * @param choices The list of available sizes
+ * @return The video size
+ */
+ private static Size chooseVideoSize(Size[] choices) {
+ for (Size size : choices) {
+ if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
+ return size;
+ }
+ }
+ Log.e(TAG, "Couldn't find any suitable video size");
+ return choices[choices.length - 1];
+ }
+
+ /**
+ * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
+ * width and height are at least as large as the respective requested values, and whose aspect
+ * ratio matches with the specified value.
+ *
+ * @param choices The list of sizes that the camera supports for the intended output class
+ * @param width The minimum desired width
+ * @param height The minimum desired height
+ * @param aspectRatio The aspect ratio
+ * @return The optimal {@code Size}, or an arbitrary one if none were big enough
+ */
+ private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List<Size> bigEnough = new ArrayList<Size>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getHeight() == option.getWidth() * h / w &&
+ option.getWidth() >= width && option.getHeight() >= height) {
+ bigEnough.add(option);
+ }
+ }
+
+ // Pick the smallest of those, assuming we found any
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -193,7 +261,6 @@
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
- mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
mButtonVideo = (Button) view.findViewById(R.id.video);
mButtonVideo.setOnClickListener(this);
view.findViewById(R.id.info).setOnClickListener(this);
@@ -202,16 +269,19 @@
@Override
public void onResume() {
super.onResume();
- openCamera();
+ startBackgroundThread();
+ if (mTextureView.isAvailable()) {
+ openCamera(mTextureView.getWidth(), mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+ }
}
@Override
public void onPause() {
+ closeCamera();
+ stopBackgroundThread();
super.onPause();
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
}
@Override
@@ -239,27 +309,59 @@
}
/**
+ * Starts a background thread and its {@link Handler}.
+ */
+ private void startBackgroundThread() {
+ mBackgroundThread = new HandlerThread("CameraBackground");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ }
+
+ /**
+ * Stops the background thread and its {@link Handler}.
+ */
+ private void stopBackgroundThread() {
+ mBackgroundThread.quitSafely();
+ try {
+ mBackgroundThread.join();
+ mBackgroundThread = null;
+ mBackgroundHandler = null;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
* Tries to open a {@link CameraDevice}. The result is listened by `mStateCallback`.
*/
- private void openCamera() {
+ private void openCamera(int width, int height) {
final Activity activity = getActivity();
- if (null == activity || activity.isFinishing() || mOpeningCamera) {
+ if (null == activity || activity.isFinishing()) {
return;
}
- mOpeningCamera = true;
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock camera opening.");
+ }
String cameraId = manager.getCameraIdList()[0];
+
+ // Choose the sizes for camera preview and video recording
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- mPreviewSize = map.getOutputSizes(SurfaceTexture.class)[0];
+ mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
+ mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
+ width, height, mVideoSize);
+
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
+ configureTransform(width, height);
+ mMediaRecorder = new MediaRecorder();
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
@@ -268,6 +370,26 @@
// Currently an NPE is thrown when the Camera2API is used but not supported on the
// device this code runs.
new ErrorDialog().show(getFragmentManager(), "dialog");
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera opening.");
+ }
+ }
+
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mMediaRecorder) {
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.");
+ } finally {
+ mCameraOpenCloseLock.release();
}
}
@@ -279,14 +401,21 @@
return;
}
try {
+ setUpMediaRecorder();
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
- mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- Surface surface = new Surface(texture);
+ mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
List<Surface> surfaces = new ArrayList<Surface>();
- surfaces.add(surface);
- mPreviewBuilder.addTarget(surface);
+
+ Surface previewSurface = new Surface(texture);
+ surfaces.add(previewSurface);
+ mPreviewBuilder.addTarget(previewSurface);
+
+ Surface recorderSurface = mMediaRecorder.getSurface();
+ surfaces.add(recorderSurface);
+ mPreviewBuilder.addTarget(recorderSurface);
+
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
@@ -302,9 +431,11 @@
Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
}
}
- }, null);
+ }, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
}
}
@@ -319,8 +450,7 @@
setUpCaptureRequestBuilder(mPreviewBuilder);
HandlerThread thread = new HandlerThread("CameraPreview");
thread.start();
- Handler backgroundHandler = new Handler(thread.getLooper());
- mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, backgroundHandler);
+ mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -361,78 +491,50 @@
mTextureView.setTransform(matrix);
}
- private void startRecordingVideo() {
+ private void setUpMediaRecorder() throws IOException {
final Activity activity = getActivity();
if (null == activity) {
return;
}
- mMediaRecorder = new MediaRecorder();
- final File file = getVideoFile(activity);
- try {
- // UI
- mButtonVideo.setText(R.string.stop);
- mIsRecordingVideo = true;
- // Configure the MediaRecorder
- mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
- mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mMediaRecorder.setOutputFile(file.getAbsolutePath());
- mMediaRecorder.setVideoEncodingBitRate(10000000);
- mMediaRecorder.setVideoFrameRate(30);
- mMediaRecorder.setVideoSize(1440, 1080);
- mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
- mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
- int orientation = ORIENTATIONS.get(rotation);
- mMediaRecorder.setOrientationHint(orientation);
- mMediaRecorder.prepare();
- Surface surface = mMediaRecorder.getSurface();
- // Set up the CaptureRequest
- final CaptureRequest.Builder builder =
- mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
- builder.addTarget(surface);
- Surface previewSurface = new Surface(mTextureView.getSurfaceTexture());
- builder.addTarget(previewSurface);
- mCameraDevice.createCaptureSession(Arrays.asList(surface, previewSurface),
- new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession session) {
- // Start recording
- try {
- session.setRepeatingRequest(builder.build(), null, null);
- mMediaRecorder.start();
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onConfigureFailed(CameraCaptureSession session) {
- Toast.makeText(activity, "Failed.", Toast.LENGTH_SHORT).show();
- }
- }, null
- );
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+ mMediaRecorder.setOutputFile(getVideoFile(activity).getAbsolutePath());
+ mMediaRecorder.setVideoEncodingBitRate(10000000);
+ mMediaRecorder.setVideoFrameRate(30);
+ mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
+ mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ int orientation = ORIENTATIONS.get(rotation);
+ mMediaRecorder.setOrientationHint(orientation);
+ mMediaRecorder.prepare();
}
private File getVideoFile(Context context) {
return new File(context.getExternalFilesDir(null), "video.mp4");
}
+ private void startRecordingVideo() {
+ try {
+ // UI
+ mButtonVideo.setText(R.string.stop);
+ mIsRecordingVideo = true;
+
+ // Start recording
+ mMediaRecorder.start();
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ }
+ }
+
private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
mButtonVideo.setText(R.string.record);
// Stop recording
mMediaRecorder.stop();
- mMediaRecorder.release();
- mMediaRecorder = null;
+ mMediaRecorder.reset();
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Video saved: " + getVideoFile(activity),
@@ -441,6 +543,20 @@
startPreview();
}
+ /**
+ * Compares two {@code Size}s based on their areas.
+ */
+ static class CompareSizesByArea implements Comparator<Size> {
+
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
+ (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+ }
+
public static class ErrorDialog extends DialogFragment {
@Override
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore b/media/HdrViewfinder/Application/.gitignore
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore
copy to media/HdrViewfinder/Application/.gitignore
diff --git a/media/HdrViewfinder/Application/README-singleview.txt b/media/HdrViewfinder/Application/README-singleview.txt
new file mode 100644
index 0000000..0cacd46
--- /dev/null
+++ b/media/HdrViewfinder/Application/README-singleview.txt
@@ -0,0 +1,47 @@
+<#--
+ Copyright 2013 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.
+-->
+
+Steps to implement SingleView template:
+-in template-params.xml.ftl:
+ -add the following line to common imports
+ <common src="activities"/>
+
+ -add a string for the action button's text using the element name "sample_action".
+ This element should be a child of <strings>:
+ <strings>
+ ...
+ <sample_action>ButtonText</sample_action>
+ ...
+ </strings>
+
+
+
+-Add a Fragment to handle behavior. In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java. Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+ For instance, if your package name is com.example.foo, create the file
+ src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/singleViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt b/media/HdrViewfinder/Application/proguard-project.txt
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt
copy to media/HdrViewfinder/Application/proguard-project.txt
diff --git a/media/HdrViewfinder/Application/src/main/AndroidManifest.xml b/media/HdrViewfinder/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..772b7df
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 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
+ package="com.example.android.hdrviewfinder"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk
+ android:minSdkVersion="21"
+ android:targetSdkVersion="21"/>
+
+ <uses-feature android:name="android.hardware.camera"/>
+ <uses-feature
+ android:name="android.hardware.camera.front"
+ android:required="false"/>
+
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
+
+ <activity
+ android:name=".HdrViewfinderActivity"
+ android:label="@string/app_name"
+ android:screenOrientation="landscape">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+
+</manifest>
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/CameraOps.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/CameraOps.java
new file mode 100644
index 0000000..5769760
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/CameraOps.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2014 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.example.android.hdrviewfinder;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.List;
+
+/**
+ * Simple interface for operating the camera, with major camera operations
+ * all performed on a background handler thread.
+ */
+public class CameraOps {
+
+ private static final String TAG = "CameraOps";
+
+ public static final long CAMERA_CLOSE_TIMEOUT = 2000; // ms
+
+ private final CameraManager mCameraManager;
+ private CameraDevice mCameraDevice;
+ private CameraCaptureSession mCameraSession;
+ private List<Surface> mSurfaces;
+
+ private final ConditionVariable mCloseWaiter = new ConditionVariable();
+
+ private HandlerThread mCameraThread;
+ private Handler mCameraHandler;
+
+ private final ErrorDisplayer mErrorDisplayer;
+
+ private final CameraReadyListener mReadyListener;
+ private final Handler mReadyHandler;
+
+ /**
+ * Create a new camera ops thread.
+ *
+ * @param errorDisplayer listener for displaying error messages
+ * @param readyListener listener for notifying when camera is ready for requests
+ * @param readyHandler the handler for calling readyListener methods on
+ */
+ CameraOps(CameraManager manager, ErrorDisplayer errorDisplayer,
+ CameraReadyListener readyListener, Handler readyHandler) {
+ mCameraThread = new HandlerThread("CameraOpsThread");
+ mCameraThread.start();
+
+ if (manager == null || errorDisplayer == null ||
+ readyListener == null || readyHandler == null) {
+ throw new IllegalArgumentException("Need valid displayer, listener, handler");
+ }
+
+ mCameraManager = manager;
+ mErrorDisplayer = errorDisplayer;
+ mReadyListener = readyListener;
+ mReadyHandler = readyHandler;
+ }
+
+ /**
+ * Open the first backfacing camera listed by the camera manager.
+ * Displays a dialog if it cannot open a camera.
+ */
+ public void openCamera(final String cameraId) {
+ mCameraHandler = new Handler(mCameraThread.getLooper());
+
+ mCameraHandler.post(new Runnable() {
+ public void run() {
+ if (mCameraDevice != null) {
+ throw new IllegalStateException("Camera already open");
+ }
+ try {
+ mCameraManager.openCamera(cameraId, mCameraDeviceListener, mCameraHandler);
+ } catch (CameraAccessException e) {
+ String errorMessage = mErrorDisplayer.getErrorString(e);
+ mErrorDisplayer.showErrorDialog(errorMessage);
+ }
+ }
+ });
+ }
+
+ /**
+ * Close the camera and wait for the close callback to be called in the camera thread.
+ * Times out after @{value CAMERA_CLOSE_TIMEOUT} ms.
+ */
+ public void closeCameraAndWait() {
+ mCloseWaiter.close();
+ mCameraHandler.post(mCloseCameraRunnable);
+ boolean closed = mCloseWaiter.block(CAMERA_CLOSE_TIMEOUT);
+ if (!closed) {
+ Log.e(TAG, "Timeout closing camera");
+ }
+ }
+
+ private Runnable mCloseCameraRunnable = new Runnable() {
+ public void run() {
+ if (mCameraDevice != null) {
+ mCameraDevice.close();
+ }
+ mCameraDevice = null;
+ mCameraSession = null;
+ mSurfaces = null;
+ }
+ };
+
+ /**
+ * Set the output Surfaces, and finish configuration if otherwise ready.
+ */
+ public void setSurfaces(final List<Surface> surfaces) {
+ mCameraHandler.post(new Runnable() {
+ public void run() {
+ mSurfaces = surfaces;
+ startCameraSession();
+ }
+ });
+ }
+
+ /**
+ * Get a request builder for the current camera.
+ */
+ public CaptureRequest.Builder createCaptureRequest(int template) throws CameraAccessException {
+ CameraDevice device = mCameraDevice;
+ if (device == null) {
+ throw new IllegalStateException("Can't get requests when no camera is open");
+ }
+ return device.createCaptureRequest(template);
+ }
+
+ /**
+ * Set a repeating request.
+ */
+ public void setRepeatingRequest(final CaptureRequest request,
+ final CameraCaptureSession.CaptureCallback listener,
+ final Handler handler) {
+ mCameraHandler.post(new Runnable() {
+ public void run() {
+ try {
+ mCameraSession.setRepeatingRequest(request, listener, handler);
+ } catch (CameraAccessException e) {
+ String errorMessage = mErrorDisplayer.getErrorString(e);
+ mErrorDisplayer.showErrorDialog(errorMessage);
+ }
+ }
+ });
+ }
+
+ /**
+ * Set a repeating request.
+ */
+ public void setRepeatingBurst(final List<CaptureRequest> requests,
+ final CameraCaptureSession.CaptureCallback listener,
+ final Handler handler) {
+ mCameraHandler.post(new Runnable() {
+ public void run() {
+ try {
+ mCameraSession.setRepeatingBurst(requests, listener, handler);
+ } catch (CameraAccessException e) {
+ String errorMessage = mErrorDisplayer.getErrorString(e);
+ mErrorDisplayer.showErrorDialog(errorMessage);
+ }
+ }
+ });
+ }
+
+ /**
+ * Configure the camera session.
+ */
+ private void startCameraSession() {
+ // Wait until both the camera device is open and the SurfaceView is ready
+ if (mCameraDevice == null || mSurfaces == null) return;
+
+ try {
+ mCameraDevice.createCaptureSession(
+ mSurfaces, mCameraSessionListener, mCameraHandler);
+ } catch (CameraAccessException e) {
+ String errorMessage = mErrorDisplayer.getErrorString(e);
+ mErrorDisplayer.showErrorDialog(errorMessage);
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ }
+
+ /**
+ * Main listener for camera session events
+ * Invoked on mCameraThread
+ */
+ private CameraCaptureSession.StateCallback mCameraSessionListener =
+ new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ mCameraSession = session;
+ mReadyHandler.post(new Runnable() {
+ public void run() {
+ // This can happen when the screen is turned off and turned back on.
+ if (null == mCameraDevice) {
+ return;
+ }
+
+ mReadyListener.onCameraReady();
+ }
+ });
+
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ mErrorDisplayer.showErrorDialog("Unable to configure the capture session");
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ };
+
+ /**
+ * Main listener for camera device events.
+ * Invoked on mCameraThread
+ */
+ private CameraDevice.StateCallback mCameraDeviceListener = new CameraDevice.StateCallback() {
+
+ @Override
+ public void onOpened(CameraDevice camera) {
+ mCameraDevice = camera;
+ startCameraSession();
+ }
+
+ @Override
+ public void onClosed(CameraDevice camera) {
+ mCloseWaiter.open();
+ }
+
+ @Override
+ public void onDisconnected(CameraDevice camera) {
+ mErrorDisplayer.showErrorDialog("The camera device has been disconnected.");
+ camera.close();
+ mCameraDevice = null;
+ }
+
+ @Override
+ public void onError(CameraDevice camera, int error) {
+ mErrorDisplayer.showErrorDialog("The camera encountered an error:" + error);
+ camera.close();
+ mCameraDevice = null;
+ }
+
+ };
+
+ /**
+ * Simple listener for main code to know the camera is ready for requests, or failed to
+ * start.
+ */
+ public interface CameraReadyListener {
+ public void onCameraReady();
+ }
+
+ /**
+ * Simple listener for displaying error messages
+ */
+ public interface ErrorDisplayer {
+ public void showErrorDialog(String errorMessage);
+
+ public String getErrorString(CameraAccessException e);
+ }
+
+}
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/FixedAspectSurfaceView.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/FixedAspectSurfaceView.java
new file mode 100644
index 0000000..48d842b
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/FixedAspectSurfaceView.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2014 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.example.android.hdrviewfinder;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+/**
+ * A SurfaceView that maintains its aspect ratio to be a desired target value.
+ *
+ * <p>Depending on the layout, the FixedAspectSurfaceView may not be able to maintain the
+ * requested aspect ratio. This can happen if both the width and the height are exactly
+ * determined by the layout. To avoid this, ensure that either the height or the width is
+ * adjustable by the view; for example, by setting the layout parameters to be WRAP_CONTENT for
+ * the dimension that is best adjusted to maintain the aspect ratio.</p>
+ */
+public class FixedAspectSurfaceView extends SurfaceView {
+
+ /**
+ * Desired width/height ratio
+ */
+ private float mAspectRatio;
+
+ private GestureDetector mGestureDetector;
+
+ public FixedAspectSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ // Get initial aspect ratio from custom attributes
+ TypedArray a =
+ context.getTheme().obtainStyledAttributes(attrs,
+ R.styleable.FixedAspectSurfaceView, 0, 0);
+ setAspectRatio(a.getFloat(
+ R.styleable.FixedAspectSurfaceView_aspectRatio, 1.f));
+ a.recycle();
+ }
+
+ /**
+ * Set the desired aspect ratio for this view.
+ *
+ * @param aspect the desired width/height ratio in the current UI orientation. Must be a
+ * positive value.
+ */
+ public void setAspectRatio(float aspect) {
+ if (aspect <= 0) {
+ throw new IllegalArgumentException("Aspect ratio must be positive");
+ }
+ mAspectRatio = aspect;
+ requestLayout();
+ }
+
+ /**
+ * Set a gesture listener to listen for touch events
+ */
+ public void setGestureListener(Context context, GestureDetector.OnGestureListener listener) {
+ if (listener == null) {
+ mGestureDetector = null;
+ } else {
+ mGestureDetector = new GestureDetector(context, listener);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ // General goal: Adjust dimensions to maintain the requested aspect ratio as much
+ // as possible. Depending on the measure specs handed down, this may not be possible
+
+ // Only set one of these to true
+ boolean scaleWidth = false;
+ boolean scaleHeight = false;
+
+ // Sort out which dimension to scale, if either can be. There are 9 combinations of
+ // possible measure specs; a few cases below handle multiple combinations
+ if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
+ // Can't adjust sizes at all, do nothing
+ } else if (widthMode == MeasureSpec.EXACTLY) {
+ // Width is fixed, heightMode either AT_MOST or UNSPECIFIED, so adjust height
+ scaleHeight = true;
+ } else if (heightMode == MeasureSpec.EXACTLY) {
+ // Height is fixed, widthMode either AT_MOST or UNSPECIFIED, so adjust width
+ scaleWidth = true;
+ } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
+ // Need to fit into box <= [width, height] in size.
+ // Maximize the View's area while maintaining aspect ratio
+ // This means keeping one dimension as large as possible and shrinking the other
+ float boxAspectRatio = width / (float) height;
+ if (boxAspectRatio > mAspectRatio) {
+ // Box is wider than requested aspect; pillarbox
+ scaleWidth = true;
+ } else {
+ // Box is narrower than requested aspect; letterbox
+ scaleHeight = true;
+ }
+ } else if (widthMode == MeasureSpec.AT_MOST) {
+ // Maximize width, heightSpec is UNSPECIFIED
+ scaleHeight = true;
+ } else if (heightMode == MeasureSpec.AT_MOST) {
+ // Maximize height, widthSpec is UNSPECIFIED
+ scaleWidth = true;
+ } else {
+ // Both MeasureSpecs are UNSPECIFIED. This is probably a pathological layout,
+ // with width == height == 0
+ // but arbitrarily scale height anyway
+ scaleHeight = true;
+ }
+
+ // Do the scaling
+ if (scaleWidth) {
+ width = (int) (height * mAspectRatio);
+ } else if (scaleHeight) {
+ height = (int) (width / mAspectRatio);
+ }
+
+ // Override width/height if needed for EXACTLY and AT_MOST specs
+ width = View.resolveSizeAndState(width, widthMeasureSpec, 0);
+ height = View.resolveSizeAndState(height, heightMeasureSpec, 0);
+
+ // Finally set the calculated dimensions
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mGestureDetector != null) {
+ return mGestureDetector.onTouchEvent(event);
+ }
+ return false;
+ }
+}
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
new file mode 100644
index 0000000..79f1bb6
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/HdrViewfinderActivity.java
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2014 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.example.android.hdrviewfinder;
+
+import android.app.Activity;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.renderscript.RenderScript;
+import android.util.Log;
+import android.util.Size;
+import android.view.GestureDetector;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A small demo of advanced camera functionality with the Android camera2 API.
+ *
+ * <p>This demo implements a real-time high-dynamic-range camera viewfinder,
+ * by alternating the sensor's exposure time between two exposure values on even and odd
+ * frames, and then compositing together the latest two frames whenever a new frame is
+ * captured.</p>
+ *
+ * <p>The demo has three modes: Regular auto-exposure viewfinder, split-screen manual exposure,
+ * and the fused HDR viewfinder. The latter two use manual exposure controlled by the user,
+ * by swiping up/down on the right and left halves of the viewfinder. The left half controls
+ * the exposure time of even frames, and the right half controls the exposure time of odd frames.
+ * </p>
+ *
+ * <p>In split-screen mode, the even frames are shown on the left and the odd frames on the right,
+ * so the user can see two different exposures of the scene simultaneously. In fused HDR mode,
+ * the even/odd frames are merged together into a single image. By selecting different exposure
+ * values for the even/odd frames, the fused image has a higher dynamic range than the regular
+ * viewfinder.</p>
+ *
+ * <p>The HDR fusion and the split-screen viewfinder processing is done with RenderScript; as is the
+ * necessary YUV->RGB conversion. The camera subsystem outputs YUV images naturally, while the GPU
+ * and display subsystems generally only accept RGB data. Therefore, after the images are
+ * fused/composited, a standard YUV->RGB color transform is applied before the the data is written
+ * to the output Allocation. The HDR fusion algorithm is very simple, and tends to result in
+ * lower-contrast scenes, but has very few artifacts and can run very fast.</p>
+ *
+ * <p>Data is passed between the subsystems (camera, RenderScript, and display) using the
+ * Android {@link android.view.Surface} class, which allows for zero-copy transport of large
+ * buffers between processes and subsystems.</p>
+ */
+public class HdrViewfinderActivity extends Activity implements
+ SurfaceHolder.Callback, CameraOps.ErrorDisplayer, CameraOps.CameraReadyListener {
+
+ private static final String TAG = "HdrViewfinderDemo";
+
+ private static final String FRAGMENT_DIALOG = "dialog";
+
+ /**
+ * View for the camera preview.
+ */
+ private FixedAspectSurfaceView mPreviewView;
+
+ /**
+ * This shows the current mode of the app.
+ */
+ private TextView mModeText;
+
+ // These show lengths of exposure for even frames, exposure for odd frames, and auto exposure.
+ private TextView mEvenExposureText, mOddExposureText, mAutoExposureText;
+
+ private Handler mUiHandler;
+
+ private CameraCharacteristics mCameraInfo;
+
+ private Surface mPreviewSurface;
+ private Surface mProcessingHdrSurface;
+ private Surface mProcessingNormalSurface;
+ CaptureRequest.Builder mHdrBuilder;
+ ArrayList<CaptureRequest> mHdrRequests = new ArrayList<CaptureRequest>(2);
+
+ CaptureRequest mPreviewRequest;
+
+ RenderScript mRS;
+ ViewfinderProcessor mProcessor;
+ CameraManager mCameraManager;
+ CameraOps mCameraOps;
+
+ private int mRenderMode = ViewfinderProcessor.MODE_NORMAL;
+
+ // Durations in nanoseconds
+ private static final long MICRO_SECOND = 1000;
+ private static final long MILLI_SECOND = MICRO_SECOND * 1000;
+ private static final long ONE_SECOND = MILLI_SECOND * 1000;
+
+ private long mOddExposure = ONE_SECOND / 33;
+ private long mEvenExposure = ONE_SECOND / 33;
+
+ private Object mOddExposureTag = new Object();
+ private Object mEvenExposureTag = new Object();
+ private Object mAutoExposureTag = new Object();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mPreviewView = (FixedAspectSurfaceView) findViewById(R.id.preview);
+ mPreviewView.getHolder().addCallback(this);
+ mPreviewView.setGestureListener(this, mViewListener);
+
+ Button helpButton = (Button) findViewById(R.id.help_button);
+ helpButton.setOnClickListener(mHelpButtonListener);
+
+ mModeText = (TextView) findViewById(R.id.mode_label);
+ mEvenExposureText = (TextView) findViewById(R.id.even_exposure);
+ mOddExposureText = (TextView) findViewById(R.id.odd_exposure);
+ mAutoExposureText = (TextView) findViewById(R.id.auto_exposure);
+
+ mUiHandler = new Handler(Looper.getMainLooper());
+
+ mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
+ mCameraOps = new CameraOps(mCameraManager,
+ /*errorDisplayer*/ this,
+ /*readyListener*/ this,
+ /*readyHandler*/ mUiHandler);
+
+ mHdrRequests.add(null);
+ mHdrRequests.add(null);
+
+ mRS = RenderScript.create(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ findAndOpenCamera();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ // Wait until camera is closed to ensure the next application can open it
+ mCameraOps.closeCameraAndWait();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.info: {
+ MessageDialogFragment.newInstance(R.string.intro_message)
+ .show(getFragmentManager(), FRAGMENT_DIALOG);
+ break;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private GestureDetector.OnGestureListener mViewListener
+ = new GestureDetector.SimpleOnGestureListener() {
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ switchRenderMode(1);
+ return true;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) return false;
+
+ float xPosition = e1.getAxisValue(MotionEvent.AXIS_X);
+ float width = mPreviewView.getWidth();
+ float height = mPreviewView.getHeight();
+
+ float xPosNorm = xPosition / width;
+ float yDistNorm = distanceY / height;
+
+ final float ACCELERATION_FACTOR = 8;
+ double scaleFactor = Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR);
+
+ // Even on left, odd on right
+ if (xPosNorm > 0.5) {
+ mOddExposure *= scaleFactor;
+ } else {
+ mEvenExposure *= scaleFactor;
+ }
+
+ setHdrBurst();
+
+ return true;
+ }
+ };
+
+ // Show help dialog
+ private View.OnClickListener mHelpButtonListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ MessageDialogFragment.newInstance(R.string.help_text)
+ .show(getFragmentManager(), FRAGMENT_DIALOG);
+ }
+ };
+
+ private void findAndOpenCamera() {
+
+ String errorMessage = "Unknown error";
+ boolean foundCamera = false;
+ try {
+ // Find first back-facing camera that has necessary capability
+ String[] cameraIds = mCameraManager.getCameraIdList();
+ for (String id : cameraIds) {
+ CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
+ int facing = info.get(CameraCharacteristics.LENS_FACING);
+
+ int level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+ boolean hasFullLevel
+ = (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
+
+ int[] capabilities = info.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ int syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY);
+ boolean hasManualControl = hasCapability(capabilities,
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
+ boolean hasEnoughCapability = hasManualControl &&
+ syncLatency == CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
+
+ // All these are guaranteed by
+ // CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking for only
+ // the things we care about expands range of devices we can run on
+ // We want:
+ // - Back-facing camera
+ // - Manual sensor control
+ // - Per-frame synchronization (so that exposure can be changed every frame)
+ if (facing == CameraCharacteristics.LENS_FACING_BACK &&
+ (hasFullLevel || hasEnoughCapability)) {
+ // Found suitable camera - get info, open, and set up outputs
+ mCameraInfo = info;
+ mCameraOps.openCamera(id);
+ configureSurfaces();
+ foundCamera = true;
+ break;
+ }
+ }
+ if (!foundCamera) {
+ errorMessage = getString(R.string.camera_no_good);
+ }
+ } catch (CameraAccessException e) {
+ errorMessage = getErrorString(e);
+ }
+
+ if (!foundCamera) {
+ showErrorDialog(errorMessage);
+ }
+ }
+
+ private boolean hasCapability(int[] capabilities, int capability) {
+ for (int c : capabilities) {
+ if (c == capability) return true;
+ }
+ return false;
+ }
+
+ private void switchRenderMode(int direction) {
+ mRenderMode = (mRenderMode + direction) % 3;
+
+ mModeText.setText(getResources().getStringArray(R.array.mode_label_array)[mRenderMode]);
+
+ if (mProcessor != null) {
+ mProcessor.setRenderMode(mRenderMode);
+ }
+ if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) {
+ mCameraOps.setRepeatingRequest(mPreviewRequest,
+ mCaptureCallback, mUiHandler);
+ } else {
+ setHdrBurst();
+ }
+ }
+
+ /**
+ * Configure the surfaceview and RS processing
+ */
+ private void configureSurfaces() {
+ // Find a good size for output - largest 16:9 aspect ratio that's less than 720p
+ final int MAX_WIDTH = 1280;
+ final float TARGET_ASPECT = 16.f / 9.f;
+ final float ASPECT_TOLERANCE = 0.1f;
+
+ StreamConfigurationMap configs =
+ mCameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ Size[] outputSizes = configs.getOutputSizes(SurfaceHolder.class);
+
+ Size outputSize = outputSizes[0];
+ float outputAspect = (float) outputSize.getWidth() / outputSize.getHeight();
+ for (Size candidateSize : outputSizes) {
+ if (candidateSize.getWidth() > MAX_WIDTH) continue;
+ float candidateAspect = (float) candidateSize.getWidth() / candidateSize.getHeight();
+ boolean goodCandidateAspect =
+ Math.abs(candidateAspect - TARGET_ASPECT) < ASPECT_TOLERANCE;
+ boolean goodOutputAspect =
+ Math.abs(outputAspect - TARGET_ASPECT) < ASPECT_TOLERANCE;
+ if ((goodCandidateAspect && !goodOutputAspect) ||
+ candidateSize.getWidth() > outputSize.getWidth()) {
+ outputSize = candidateSize;
+ outputAspect = candidateAspect;
+ }
+ }
+ Log.i(TAG, "Resolution chosen: " + outputSize);
+
+ // Configure processing
+ mProcessor = new ViewfinderProcessor(mRS, outputSize);
+ setupProcessor();
+
+ // Configure the output view - this will fire surfaceChanged
+ mPreviewView.setAspectRatio(outputAspect);
+ mPreviewView.getHolder().setFixedSize(outputSize.getWidth(), outputSize.getHeight());
+ }
+
+ /**
+ * Once camera is open and output surfaces are ready, configure the RS processing
+ * and the camera device inputs/outputs.
+ */
+ private void setupProcessor() {
+ if (mProcessor == null || mPreviewSurface == null) return;
+
+ mProcessor.setOutputSurface(mPreviewSurface);
+ mProcessingHdrSurface = mProcessor.getInputHdrSurface();
+ mProcessingNormalSurface = mProcessor.getInputNormalSurface();
+
+ List<Surface> cameraOutputSurfaces = new ArrayList<Surface>();
+ cameraOutputSurfaces.add(mProcessingHdrSurface);
+ cameraOutputSurfaces.add(mProcessingNormalSurface);
+
+ mCameraOps.setSurfaces(cameraOutputSurfaces);
+ }
+
+ /**
+ * Start running an HDR burst on a configured camera session
+ */
+ public void setHdrBurst() {
+
+ mHdrBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 1600);
+ mHdrBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, ONE_SECOND / 30);
+
+ mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, mEvenExposure);
+ mHdrBuilder.setTag(mEvenExposureTag);
+ mHdrRequests.set(0, mHdrBuilder.build());
+
+ mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, mOddExposure);
+ mHdrBuilder.setTag(mOddExposureTag);
+ mHdrRequests.set(1, mHdrBuilder.build());
+
+ mCameraOps.setRepeatingBurst(mHdrRequests, mCaptureCallback, mUiHandler);
+ }
+
+ /**
+ * Listener for completed captures
+ * Invoked on UI thread
+ */
+ private CameraCaptureSession.CaptureCallback mCaptureCallback
+ = new CameraCaptureSession.CaptureCallback() {
+
+ public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+ TotalCaptureResult result) {
+
+ // Only update UI every so many frames
+ // Use an odd number here to ensure both even and odd exposures get an occasional update
+ long frameNumber = result.getFrameNumber();
+ if (frameNumber % 3 != 0) return;
+
+ long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+
+ // Format exposure time nicely
+ String exposureText;
+ if (exposureTime > ONE_SECOND) {
+ exposureText = String.format("%.2f s", exposureTime / 1e9);
+ } else if (exposureTime > MILLI_SECOND) {
+ exposureText = String.format("%.2f ms", exposureTime / 1e6);
+ } else if (exposureTime > MICRO_SECOND) {
+ exposureText = String.format("%.2f us", exposureTime / 1e3);
+ } else {
+ exposureText = String.format("%d ns", exposureTime);
+ }
+
+ Object tag = request.getTag();
+ Log.i(TAG, "Exposure: " + exposureText);
+
+ if (tag == mEvenExposureTag) {
+ mEvenExposureText.setText(exposureText);
+
+ mEvenExposureText.setEnabled(true);
+ mOddExposureText.setEnabled(true);
+ mAutoExposureText.setEnabled(false);
+ } else if (tag == mOddExposureTag) {
+ mOddExposureText.setText(exposureText);
+
+ mEvenExposureText.setEnabled(true);
+ mOddExposureText.setEnabled(true);
+ mAutoExposureText.setEnabled(false);
+ } else {
+ mAutoExposureText.setText(exposureText);
+
+ mEvenExposureText.setEnabled(false);
+ mOddExposureText.setEnabled(false);
+ mAutoExposureText.setEnabled(true);
+ }
+ }
+ };
+
+ /**
+ * Callbacks for the FixedAspectSurfaceView
+ */
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ mPreviewSurface = holder.getSurface();
+
+ setupProcessor();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ // ignored
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ mPreviewSurface = null;
+ }
+
+ /**
+ * Callbacks for CameraOps
+ */
+ @Override
+ public void onCameraReady() {
+ // Ready to send requests in, so set them up
+ try {
+ CaptureRequest.Builder previewBuilder =
+ mCameraOps.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ previewBuilder.addTarget(mProcessingNormalSurface);
+ previewBuilder.setTag(mAutoExposureTag);
+ mPreviewRequest = previewBuilder.build();
+
+ mHdrBuilder =
+ mCameraOps.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mHdrBuilder.set(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_OFF);
+ mHdrBuilder.addTarget(mProcessingHdrSurface);
+
+ switchRenderMode(0);
+
+ } catch (CameraAccessException e) {
+ String errorMessage = getErrorString(e);
+ showErrorDialog(errorMessage);
+ }
+ }
+
+ /**
+ * Utility methods
+ */
+ @Override
+ public void showErrorDialog(String errorMessage) {
+ MessageDialogFragment.newInstance(errorMessage).show(getFragmentManager(), FRAGMENT_DIALOG);
+ }
+
+ @Override
+ public String getErrorString(CameraAccessException e) {
+ String errorMessage;
+ switch (e.getReason()) {
+ case CameraAccessException.CAMERA_DISABLED:
+ errorMessage = getString(R.string.camera_disabled);
+ break;
+ case CameraAccessException.CAMERA_DISCONNECTED:
+ errorMessage = getString(R.string.camera_disconnected);
+ break;
+ case CameraAccessException.CAMERA_ERROR:
+ errorMessage = getString(R.string.camera_error);
+ break;
+ default:
+ errorMessage = getString(R.string.camera_unknown, e.getReason());
+ break;
+ }
+ return errorMessage;
+ }
+
+}
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/MessageDialogFragment.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/MessageDialogFragment.java
new file mode 100644
index 0000000..b1bdf9e
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/MessageDialogFragment.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 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.example.android.hdrviewfinder;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.os.Bundle;
+
+public class MessageDialogFragment extends DialogFragment {
+
+ private static final String ARG_MESSAGE_INT = "message_int";
+ private static final String ARG_MESSAGE_STRING = "message_string";
+
+ public static MessageDialogFragment newInstance(int message) {
+ MessageDialogFragment fragment = new MessageDialogFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_MESSAGE_INT, message);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public static MessageDialogFragment newInstance(String message) {
+ MessageDialogFragment fragment = new MessageDialogFragment();
+ Bundle args = new Bundle();
+ args.putString(ARG_MESSAGE_STRING, message);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setPositiveButton(android.R.string.ok, null);
+ Bundle args = getArguments();
+ if (args.containsKey(ARG_MESSAGE_INT)) {
+ builder.setMessage(args.getInt(ARG_MESSAGE_INT));
+ } else if (args.containsKey(ARG_MESSAGE_STRING)) {
+ builder.setMessage(args.getString(ARG_MESSAGE_STRING));
+ }
+ return builder.create();
+ }
+
+}
diff --git a/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/ViewfinderProcessor.java b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/ViewfinderProcessor.java
new file mode 100644
index 0000000..f51dfaa
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/java/com/example/android/hdrviewfinder/ViewfinderProcessor.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 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.example.android.hdrviewfinder;
+
+import android.graphics.ImageFormat;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Size;
+import android.view.Surface;
+
+/**
+ * Renderscript-based merger for an HDR viewfinder
+ */
+public class ViewfinderProcessor {
+
+ private Allocation mInputHdrAllocation;
+ private Allocation mInputNormalAllocation;
+ private Allocation mPrevAllocation;
+ private Allocation mOutputAllocation;
+
+ private Surface mOutputSurface;
+ private HandlerThread mProcessingThread;
+ private Handler mProcessingHandler;
+ private ScriptC_hdr_merge mHdrMergeScript;
+
+ public ProcessingTask mHdrTask;
+ public ProcessingTask mNormalTask;
+
+ private Size mSize;
+
+ private int mMode;
+
+ public final static int MODE_NORMAL = 0;
+ public final static int MODE_SIDE_BY_SIDE = 1;
+ public final static int MODE_HDR = 2;
+
+ public ViewfinderProcessor(RenderScript rs, Size dimensions) {
+ mSize = dimensions;
+
+ Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs));
+ yuvTypeBuilder.setX(dimensions.getWidth());
+ yuvTypeBuilder.setY(dimensions.getHeight());
+ yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
+ mInputHdrAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
+ Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
+ mInputNormalAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
+ Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
+
+ Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs));
+ rgbTypeBuilder.setX(dimensions.getWidth());
+ rgbTypeBuilder.setY(dimensions.getHeight());
+ mPrevAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
+ Allocation.USAGE_SCRIPT);
+ mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
+ Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
+
+ mProcessingThread = new HandlerThread("ViewfinderProcessor");
+ mProcessingThread.start();
+ mProcessingHandler = new Handler(mProcessingThread.getLooper());
+
+ mHdrMergeScript = new ScriptC_hdr_merge(rs);
+
+ mHdrMergeScript.set_gPrevFrame(mPrevAllocation);
+
+ mHdrTask = new ProcessingTask(mInputHdrAllocation, dimensions.getWidth()/2, true);
+ mNormalTask = new ProcessingTask(mInputNormalAllocation, 0, false);
+
+ setRenderMode(MODE_NORMAL);
+ }
+
+ public Surface getInputHdrSurface() {
+ return mInputHdrAllocation.getSurface();
+ }
+
+ public Surface getInputNormalSurface() {
+ return mInputNormalAllocation.getSurface();
+ }
+
+ public void setOutputSurface(Surface output) {
+ mOutputAllocation.setSurface(output);
+ }
+
+ public void setRenderMode(int mode) {
+ mMode = mode;
+ }
+
+ /**
+ * Simple class to keep track of incoming frame count,
+ * and to process the newest one in the processing thread
+ */
+ class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener {
+ private int mPendingFrames = 0;
+ private int mFrameCounter = 0;
+ private int mCutPointX;
+ private boolean mCheckMerge;
+
+ private Allocation mInputAllocation;
+
+ public ProcessingTask(Allocation input, int cutPointX, boolean checkMerge) {
+ mInputAllocation = input;
+ mInputAllocation.setOnBufferAvailableListener(this);
+ mCutPointX = cutPointX;
+ mCheckMerge = checkMerge;
+ }
+
+ @Override
+ public void onBufferAvailable(Allocation a) {
+ synchronized(this) {
+ mPendingFrames++;
+ mProcessingHandler.post(this);
+ }
+ }
+
+ @Override
+ public void run() {
+
+ // Find out how many frames have arrived
+ int pendingFrames;
+ synchronized(this) {
+ pendingFrames = mPendingFrames;
+ mPendingFrames = 0;
+
+ // Discard extra messages in case processing is slower than frame rate
+ mProcessingHandler.removeCallbacks(this);
+ }
+
+ // Get to newest input
+ for (int i = 0; i < pendingFrames; i++) {
+ mInputAllocation.ioReceive();
+ }
+
+ mHdrMergeScript.set_gFrameCounter(mFrameCounter++);
+ mHdrMergeScript.set_gCurrentFrame(mInputAllocation);
+ mHdrMergeScript.set_gCutPointX(mCutPointX);
+ if (mCheckMerge && mMode == MODE_HDR) {
+ mHdrMergeScript.set_gDoMerge(1);
+ } else {
+ mHdrMergeScript.set_gDoMerge(0);
+ }
+
+ // Run processing pass
+ mHdrMergeScript.forEach_mergeHdrFrames(mPrevAllocation, mOutputAllocation);
+ mOutputAllocation.ioSend();
+ }
+ }
+
+}
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_action_info.png b/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000..32bd1aa
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_launcher.png b/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..18f79c1
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_action_info.png b/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000..8efbbf8
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_launcher.png b/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..e70a7dc
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_action_info.png b/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000..ba143ea
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..ed25c5a
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_action_info.png b/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_action_info.png
new file mode 100644
index 0000000..394eb7e
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_action_info.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..90867ff
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/media/HdrViewfinder/Application/src/main/res/layout/main.xml b/media/HdrViewfinder/Application/src/main/res/layout/main.xml
new file mode 100644
index 0000000..7507709
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/layout/main.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<LinearLayout
+ android:id="@+id/panels"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <com.example.android.hdrviewfinder.FixedAspectSurfaceView
+ android:id="@+id/preview"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="4"
+ custom:aspectRatio="1.333"/>
+
+ <LinearLayout
+ android:id="@+id/control_bar_contents"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/help_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/help_button"/>
+
+ <TextView
+ android:id="@+id/mode_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="16sp"
+ tools:text="MODE: HDR"/>
+
+ <TextView
+ android:id="@+id/auto_exposure_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/auto_exposure_label"/>
+
+ <TextView
+ android:id="@+id/auto_exposure"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textSize="20sp"
+ tools:text="33.33 ms"/>
+
+ <TextView
+ android:id="@+id/even_exposure_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/even_exposure_label"/>
+
+ <TextView
+ android:id="@+id/even_exposure"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textSize="20sp"
+ tools:text="30.30 ms"/>
+
+ <TextView
+ android:id="@+id/odd_exposure_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/odd_exposure_label"/>
+
+ <TextView
+ android:id="@+id/odd_exposure"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textSize="20sp"
+ tools:text="30.30 ms"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/media/HdrViewfinder/Application/src/main/res/menu/main.xml b/media/HdrViewfinder/Application/src/main/res/menu/main.xml
new file mode 100644
index 0000000..14b2ffa
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/menu/main.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/info"
+ android:icon="@drawable/ic_action_info"
+ android:showAsAction="always"
+ android:title="@string/info"/>
+
+</menu>
\ No newline at end of file
diff --git a/media/HdrViewfinder/Application/src/main/res/values/attrs.xml b/media/HdrViewfinder/Application/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..ec8a564
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<resources>
+ <declare-styleable name="FixedAspectSurfaceView">
+ <attr name="aspectRatio" format="float"/>
+ </declare-styleable>
+</resources>
diff --git a/media/HdrViewfinder/Application/src/main/res/values/strings.xml b/media/HdrViewfinder/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..21838d5
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/res/values/strings.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (C) 2013 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.
+-->
+
+<resources>
+
+ <string name="help_button">Help</string>
+
+ <string-array name="mode_label_array">
+ <!-- must be in same order as ViewfinderProcessor.MODE_ ints -->
+ <item>Mode: Normal</item>
+ <item>Mode: Split</item>
+ <item>Mode: HDR</item>
+ </string-array>
+
+ <string name="auto_exposure_label">Auto exp. time:</string>
+ <string name="even_exposure_label">Even exp. time:</string>
+ <string name="odd_exposure_label">Odd exp. time:</string>
+
+ <string name="help_text">
+ <b>HDR Viewfinder Demo:</b>\n\n
+
+ Tap viewfinder to switch modes.\n\n
+
+ <b>Normal:</b> Standard camera preview\n
+ <b>Split:</b> Manual exposure control\n
+ <b>HDR:</b> Fused HDR viewfinder\n\n
+
+ Swipe up/down in Split/HDR modes to change manual exposure
+ values.\n\n
+
+ The left half of the viewfinder controls exposure time for
+ even-numbered frames, and the right half of the viewfinder
+ controls exposure time for odd-numbered frames
+ </string>
+
+ <string name="info">Info</string>
+
+ <string name="camera_no_good">No back-facing sufficiently capable camera available!</string>
+ <string name="camera_disabled">Camera is disabled by device policy</string>
+ <string name="camera_disconnected">Camera was disconnected before it was opened</string>
+ <string name="camera_error">Camera service reported an error</string>
+ <string name="camera_unknown">Unknown camera error: %s</string>
+
+</resources>
diff --git a/media/HdrViewfinder/Application/src/main/rs/hdr_merge.rs b/media/HdrViewfinder/Application/src/main/rs/hdr_merge.rs
new file mode 100644
index 0000000..f176fd7
--- /dev/null
+++ b/media/HdrViewfinder/Application/src/main/rs/hdr_merge.rs
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.hdrviewfinder)
+#pragma rs_fp_relaxed
+
+rs_allocation gCurrentFrame;
+rs_allocation gPrevFrame;
+
+int gCutPointX = 0;
+int gDoMerge = 0;
+int gFrameCounter = 0;
+
+uchar4 __attribute__((kernel)) mergeHdrFrames(uchar4 prevPixel, uint32_t x, uint32_t y) {
+
+ // Read in pixel values from latest frame - YUV color space
+
+ uchar4 curPixel;
+ curPixel.r = rsGetElementAtYuv_uchar_Y(gCurrentFrame, x, y);
+ curPixel.g = rsGetElementAtYuv_uchar_U(gCurrentFrame, x, y);
+ curPixel.b = rsGetElementAtYuv_uchar_V(gCurrentFrame, x, y);
+ curPixel.a = 255;
+
+ uchar4 mergedPixel;
+ if (gDoMerge == 1) {
+ // Complex HDR fusion technique
+ mergedPixel = curPixel / 2 + prevPixel / 2;
+
+ /* Experimental color saturation boosting merge
+ mergedPixel.r = curPixel.r / 2 + prevPixel.r / 2;
+
+ uchar saturationCurrent = abs(curPixel.g - 128) + abs(curPixel.b - 128);
+ uchar saturationPrev = abs(prevPixel.g - 128) + abs(prevPixel.b - 128);
+ mergedPixel.g = saturationCurrent > saturationPrev ? curPixel.g : prevPixel.g;
+ mergedPixel.b = saturationCurrent > saturationPrev ? curPixel.b : prevPixel.b;
+ */
+ } else if (gCutPointX > 0) {
+ // Composite side by side
+ mergedPixel = ((x < gCutPointX) ^ (gFrameCounter & 0x1)) ?
+ curPixel : prevPixel;
+ } else {
+ // Straight passthrough
+ mergedPixel = curPixel;
+ }
+
+ // Convert YUV to RGB, JFIF transform with fixed-point math
+ // R = Y + 1.402 * (V - 128)
+ // G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)
+ // B = Y + 1.772 * (U - 128)
+
+ int4 rgb;
+ rgb.r = mergedPixel.r +
+ mergedPixel.b * 1436 / 1024 - 179;
+ rgb.g = mergedPixel.r -
+ mergedPixel.g * 46549 / 131072 + 44 -
+ mergedPixel.b * 93604 / 131072 + 91;
+ rgb.b = mergedPixel.r +
+ mergedPixel.g * 1814 / 1024 - 227;
+ rgb.a = 255;
+
+ // Store current pixel for next frame
+ rsSetElementAt_uchar4(gPrevFrame, curPixel, x, y);
+
+ // Write out merged HDR result
+ uchar4 out = convert_uchar4(clamp(rgb, 0, 255));
+
+ return out;
+}
diff --git a/media/HdrViewfinder/CONTRIB.md b/media/HdrViewfinder/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/media/HdrViewfinder/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/media/HdrViewfinder/LICENSE b/media/HdrViewfinder/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/media/HdrViewfinder/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 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.
diff --git a/media/HdrViewfinder/README.md b/media/HdrViewfinder/README.md
new file mode 100644
index 0000000..46adfbb
--- /dev/null
+++ b/media/HdrViewfinder/README.md
@@ -0,0 +1,82 @@
+Android HdrViewfinder Sample
+==============================
+
+This demo shows how to use Camera2 API and RenderScript to implement an HDR viewfinder.
+
+Introduction
+------------
+
+This demo implements a real-time high-dynamic-range camera viewfinder, by alternating the sensor's
+exposure time between two exposure values on even and odd frames, and then compositing together the
+latest two frames whenever a new frame is captured.
+
+The demo has three modes: Regular auto-exposure viewfinder, split-screen manual exposure, and the
+fused HDR viewfinder. The latter two use manual exposure controlled by the user, by swiping up/down
+on the right and left halves of the viewfinder. The left half controls the exposure time of even
+frames, and the right half controls the exposure time of odd frames.
+
+In split-screen mode, the even frames are shown on the left and the odd frames on the right, so the
+user can see two different exposures of the scene simultaneously. In fused HDR mode, the even/odd
+frames are merged together into a single image. By selecting different exposure values for the
+even/odd frames, the fused image has a higher dynamic range than the regular viewfinder.
+
+The HDR fusion and the split-screen viewfinder processing is done with RenderScript; as is the
+necessary YUV->RGB conversion. The camera subsystem outputs YUV images naturally, while the GPU and
+display subsystems generally only accept RGB data. Therefore, after the images are
+fused/composited, a standard YUV->RGB color transform is applied before the the data is written to
+the output Allocation. The HDR fusion algorithm is very simple, and tends to result in
+lower-contrast scenes, but has very few artifacts and can run very fast.
+
+Data is passed between the subsystems (camera, RenderScript, and display) using the Android {@link
+android.view.Surface} class, which allows for zero-copy transport of large buffers between processes
+and subsystems.
+
+Pre-requisites
+--------------
+
+- Android SDK v21
+- Android Build Tools v21
+- Android Support Repository
+
+Getting Started
+---------------
+
+This sample uses the Gradle build system. To build this project, use the
+"gradlew build" command or use "Import Project" in Android Studio.
+
+Screenshots
+-----------
+
+
+
+Support
+-------
+
+- Google+ Community: https://plus.google.com/communities/105153134372062985968
+- Stack Overflow: http://stackoverflow.com/questions/tagged/android
+
+If you've found an error in this sample, please file an issue:
+https://github.com/googlesamples/android-HdrViewfinder
+
+Patches are encouraged, and may be submitted by forking this project and
+submitting a pull request through GitHub. Please see CONTRIBUTING.md for more details.
+
+License
+-------
+
+Copyright 2014 The Android Open Source Project, Inc.
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements. See the NOTICE file distributed with this work for
+additional information regarding copyright ownership. The ASF licenses this
+file to you 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.
diff --git a/media/HdrViewfinder/big_icon.png b/media/HdrViewfinder/big_icon.png
new file mode 100644
index 0000000..b38019c
--- /dev/null
+++ b/media/HdrViewfinder/big_icon.png
Binary files differ
diff --git a/media/HdrViewfinder/build.gradle b/media/HdrViewfinder/build.gradle
new file mode 100644
index 0000000..2b8d1ef
--- /dev/null
+++ b/media/HdrViewfinder/build.gradle
@@ -0,0 +1,11 @@
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../build"
+ pathToSamplesCommon "../../common"
+}
+apply from: "../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/media/HdrViewfinder/buildSrc/build.gradle b/media/HdrViewfinder/buildSrc/build.gradle
new file mode 100644
index 0000000..8c294c2
--- /dev/null
+++ b/media/HdrViewfinder/buildSrc/build.gradle
@@ -0,0 +1,15 @@
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar b/media/HdrViewfinder/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar
copy to media/HdrViewfinder/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/media/HdrViewfinder/gradle/wrapper/gradle-wrapper.properties b/media/HdrViewfinder/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/media/HdrViewfinder/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew b/media/HdrViewfinder/gradlew
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew
copy to media/HdrViewfinder/gradlew
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew.bat b/media/HdrViewfinder/gradlew.bat
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/gradlew.bat
copy to media/HdrViewfinder/gradlew.bat
diff --git a/media/HdrViewfinder/packaging.yaml b/media/HdrViewfinder/packaging.yaml
new file mode 100644
index 0000000..c13e3ed
--- /dev/null
+++ b/media/HdrViewfinder/packaging.yaml
@@ -0,0 +1,15 @@
+# GOOGLE SAMPLE PACKAGING DATA
+#
+# This file is used by Google as part of our samples packaging process.
+# End users may safely ignore this file. It has no relevance to other systems.
+---
+
+status: PUBLISHED
+technologies: [Android]
+categories: [Media]
+languages: [Java]
+solutions: [Mobile]
+github: googlesamples/android-HdrViewfinder
+level: INTERMEDIATE
+icon: media/HdrViewfinder/big_icon.png
+license: apache2-android
diff --git a/media/HdrViewfinder/screenshots/image1.png b/media/HdrViewfinder/screenshots/image1.png
new file mode 100755
index 0000000..75c8db1
--- /dev/null
+++ b/media/HdrViewfinder/screenshots/image1.png
Binary files differ
diff --git a/media/HdrViewfinder/settings.gradle b/media/HdrViewfinder/settings.gradle
new file mode 100644
index 0000000..9464a35
--- /dev/null
+++ b/media/HdrViewfinder/settings.gradle
@@ -0,0 +1 @@
+include 'Application'
diff --git a/ui/activitytasks/DocumentCentricRecents/template-params.xml b/media/HdrViewfinder/template-params.xml
similarity index 62%
copy from ui/activitytasks/DocumentCentricRecents/template-params.xml
copy to media/HdrViewfinder/template-params.xml
index d83182e..89c0056 100644
--- a/ui/activitytasks/DocumentCentricRecents/template-params.xml
+++ b/media/HdrViewfinder/template-params.xml
@@ -14,24 +14,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
<sample>
- <name>DocumentCentricRecents</name>
- <group>UI</group>
- <package>com.example.android.documentcentricrecents</package>
+ <name>HdrViewfinder</name>
+ <group>Media</group>
+ <package>com.example.android.hdrviewfinder</package>
- <!-- change minSdk if needed-->
<minSdk>21</minSdk>
<strings>
<intro>
<![CDATA[
- This sample shows the basic usage of the new \"Document Centric Recents\" API.
- It let\'s you create new documents in the recents history and persists its
- state through reboots. If \"Task per document\" is checked a new task will be
- created for every new document in recents.
+ This demo implements a real-time high-dynamic-range camera viewfinder, by alternating
+ the sensor\'s exposure time between two exposure values on even and odd frames, and then
+ compositing together the latest two frames whenever a new frame is captured.
]]>
</intro>
</strings>
diff --git a/media/MediaRouter/Application/src/main/AndroidManifest.xml b/media/MediaRouter/Application/src/main/AndroidManifest.xml
index 0b5bec4..1805749 100644
--- a/media/MediaRouter/Application/src/main/AndroidManifest.xml
+++ b/media/MediaRouter/Application/src/main/AndroidManifest.xml
@@ -28,9 +28,8 @@
remote display using system alert window. -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- <uses-sdk android:targetSdkVersion="19"
- android:minSdkVersion="7"/>
-
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
+
<!-- The smallest screen this app works on is a phone. The app will
scale its UI to larger screens but doesn't make good use of them
so allow the compatibility mode button to be shown (mostly because
diff --git a/security/keystore/BasicAndroidKeyStore/Application/src/main/AndroidManifest.xml b/security/keystore/BasicAndroidKeyStore/Application/src/main/AndroidManifest.xml
index 28d256c..1c3b255 100644
--- a/security/keystore/BasicAndroidKeyStore/Application/src/main/AndroidManifest.xml
+++ b/security/keystore/BasicAndroidKeyStore/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/sensors/BatchStepSensor/Application/src/main/AndroidManifest.xml b/sensors/BatchStepSensor/Application/src/main/AndroidManifest.xml
index 2c4e4f2..9063770 100644
--- a/sensors/BatchStepSensor/Application/src/main/AndroidManifest.xml
+++ b/sensors/BatchStepSensor/Application/src/main/AndroidManifest.xml
@@ -23,7 +23,7 @@
android:versionName="1.0">
<!-- This sample requires at least Android KitKat for sensor batching support -->
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<!-- Require the step counter and step detector sensors.
See the method BatchStepSensorFragment#isKitkatWithStepSensor() for a programmatic check if
diff --git a/testing/ActivityInstrumentation/Application/src/main/AndroidManifest.xml b/testing/ActivityInstrumentation/Application/src/main/AndroidManifest.xml
index 547d95e..da5c824 100644
--- a/testing/ActivityInstrumentation/Application/src/main/AndroidManifest.xml
+++ b/testing/ActivityInstrumentation/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/DrawableTinting/Application/src/main/AndroidManifest.xml b/ui/DrawableTinting/Application/src/main/AndroidManifest.xml
index eb737b6..9aa3976 100644
--- a/ui/DrawableTinting/Application/src/main/AndroidManifest.xml
+++ b/ui/DrawableTinting/Application/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="android-L" android:targetSdkVersion="android-L" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/DrawableTinting/template-params.xml b/ui/DrawableTinting/template-params.xml
index 5c3bd62..dfc3960 100644
--- a/ui/DrawableTinting/template-params.xml
+++ b/ui/DrawableTinting/template-params.xml
@@ -18,7 +18,7 @@
<group>UI</group>
<package>com.example.android.drawabletinting</package>
<!-- change minSdk if needed-->
- <minSdk>L</minSdk>
+ <minSdk>21</minSdk>
<strings>
<intro>
<![CDATA[
diff --git a/ui/Interpolator/Application/src/main/AndroidManifest.xml b/ui/Interpolator/Application/src/main/AndroidManifest.xml
index 180f78a..85f50b2 100644
--- a/ui/Interpolator/Application/src/main/AndroidManifest.xml
+++ b/ui/Interpolator/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="android-L" android:targetSdkVersion="android-L" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/Interpolator/template-params.xml b/ui/Interpolator/template-params.xml
index 6549b44..268ee8a 100644
--- a/ui/Interpolator/template-params.xml
+++ b/ui/Interpolator/template-params.xml
@@ -23,7 +23,7 @@
<package>com.example.android.interpolator</package>
<!-- change minSdk if needed-->
- <minSdk>L</minSdk>
+ <minSdk>21</minSdk>
<strings>
<intro>
diff --git a/ui/actionbar/DoneBar/Application/src/main/AndroidManifest.xml b/ui/actionbar/DoneBar/Application/src/main/AndroidManifest.xml
index 4731114..820fae5 100644
--- a/ui/actionbar/DoneBar/Application/src/main/AndroidManifest.xml
+++ b/ui/actionbar/DoneBar/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
diff --git a/ui/activityscenetransition/ActivitySceneTransitionBasic/Application/src/main/AndroidManifest.xml b/ui/activityscenetransition/ActivitySceneTransitionBasic/Application/src/main/AndroidManifest.xml
index 0eb7210..ae64d6f 100644
--- a/ui/activityscenetransition/ActivitySceneTransitionBasic/Application/src/main/AndroidManifest.xml
+++ b/ui/activityscenetransition/ActivitySceneTransitionBasic/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore b/ui/activitytasks/DocumentCentricApps/Application/.gitignore
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/.gitignore
rename to ui/activitytasks/DocumentCentricApps/Application/.gitignore
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt b/ui/activitytasks/DocumentCentricApps/Application/proguard-project.txt
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/proguard-project.txt
rename to ui/activitytasks/DocumentCentricApps/Application/proguard-project.txt
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml b/ui/activitytasks/DocumentCentricApps/Application/src/main/AndroidManifest.xml
similarity index 84%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/AndroidManifest.xml
index 71ac7d0..a1378ef 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/AndroidManifest.xml
+++ b/ui/activitytasks/DocumentCentricApps/Application/src/main/AndroidManifest.xml
@@ -16,18 +16,16 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.documentcentricrecents"
+ package="com.example.android.documentcentricapps"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="android-L" android:targetSdkVersion="android-L" />
-
<application android:allowBackup="true"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">
- <activity android:name=".DocumentCentricActivity"
+ <activity android:name="com.example.android.documentcentricapps.DocumentCentricActivity"
android:label="@string/app_name"
android:persistableMode="persistAcrossReboots">
<intent-filter>
@@ -36,7 +34,7 @@
</intent-filter>
</activity>
<activity
- android:name=".NewDocumentActivity"
+ android:name="com.example.android.documentcentricapps.NewDocumentActivity"
android:label="@string/activity_new_document_title" >
</activity>
</application>
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/DocumentCentricActivity.java b/ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/DocumentCentricActivity.java
similarity index 93%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/DocumentCentricActivity.java
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/DocumentCentricActivity.java
index 1d2dcee..92b5b43 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/DocumentCentricActivity.java
+++ b/ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/DocumentCentricActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.example.android.documentcentricrecents;
+package com.example.android.documentcentricapps;
import android.app.Activity;
import android.content.Intent;
@@ -25,7 +25,7 @@
import android.widget.CheckBox;
/**
- * DocumentCentricActivity shows the basic usage of the new Document-Centric Recents API. The new
+ * DocumentCentricActivity shows the basic usage of the new Document-Centric Apps API. The new
* API modifies the meaning of the {@link Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET} flag, which is
* now deprecated. In versions before L it serves to define a boundary between the main task and a
* subtask. The subtask holds a different thumbnail and all activities in it are finished when the
@@ -56,7 +56,7 @@
}
@Override
- protected void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
+ public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
// Restore state from PersistableBundle
if (persistentState != null) {
@@ -65,7 +65,7 @@
}
@Override
- protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+ public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
/*
To maintain activity state across reboots the system saves and restore critical information for
all tasks and their activities. Information known by the system includes the activity stack order,
@@ -94,7 +94,8 @@
/**
- * Returns an new {@link Intent} to start {@link NewDocumentActivity} as a new document in recents.
+ * Returns an new {@link Intent} to start {@link NewDocumentActivity} as a new document in
+ * overview menu.
*
* To start a new document task {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT} must be used. The
* system will search through existing tasks for one whose Intent matches the Intent component
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/NewDocumentActivity.java b/ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/NewDocumentActivity.java
similarity index 88%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/NewDocumentActivity.java
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/NewDocumentActivity.java
index c94ad34..ac5e4f3 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/java/com/example/android/documentcentricrecents/NewDocumentActivity.java
+++ b/ui/activitytasks/DocumentCentricApps/Application/src/main/java/com/example/android/documentcentricapps/NewDocumentActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.example.android.documentcentricrecents;
+package com.example.android.documentcentricapps;
import android.app.Activity;
import android.content.Intent;
@@ -23,7 +23,7 @@
import android.widget.TextView;
/**
- * Represents a "document" in the new recents notion. This is just a placeholder.
+ * Represents a "document" in the new overview notion. This is just a placeholder.
* Real world examples of this could be:
*
* <ul>
@@ -59,8 +59,8 @@
setDocumentCounterText(R.string.reusing_document_counter);
}
- public void onRemoveFromRecents(View view) {
- // It is good pratice to remove a document from the recents stack if not needed anymore.
+ public void onRemoveFromOverview(View view) {
+ // It is good pratice to remove a document from the overview stack if not needed anymore.
finishAndRemoveTask();
}
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-hdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-hdpi/ic_launcher.png
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-hdpi/ic_launcher.png
copy to ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-mdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-mdpi/ic_launcher.png
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-mdpi/ic_launcher.png
copy to ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xhdpi/ic_launcher.png
copy to ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xxhdpi/ic_launcher.png
copy to ui/activitytasks/DocumentCentricApps/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/layout/activity_document_centric_main.xml b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/layout/activity_document_centric_main.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/layout/activity_document_centric_main.xml
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/res/layout/activity_document_centric_main.xml
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/layout/activity_new_document.xml b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/layout/activity_new_document.xml
similarity index 96%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/layout/activity_new_document.xml
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/res/layout/activity_new_document.xml
index 3dc7a4a..2a6c58a 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/layout/activity_new_document.xml
+++ b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/layout/activity_new_document.xml
@@ -36,6 +36,6 @@
android:layout_marginTop="@dimen/margin_small"
android:layout_marginLeft="@dimen/margin_small"
android:text="@string/remove_task_button_text"
- android:onClick="onRemoveFromRecents" />
+ android:onClick="onRemoveFromOverview" />
</LinearLayout>
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/dimens.xml b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/values/dimens.xml
similarity index 100%
copy from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/dimens.xml
copy to ui/activitytasks/DocumentCentricApps/Application/src/main/res/values/dimens.xml
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/strings.xml b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/values/strings.xml
similarity index 93%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/strings.xml
rename to ui/activitytasks/DocumentCentricApps/Application/src/main/res/values/strings.xml
index 56f801f..5f0e3f0 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/strings.xml
+++ b/ui/activitytasks/DocumentCentricApps/Application/src/main/res/values/strings.xml
@@ -23,6 +23,6 @@
<string name="activity_new_document_title">DocumentActivity</string>
<string name="new_document_button_text">Create new document</string>
<string name="multiple_task_checkbox_label">Task per document</string>
- <string name="remove_task_button_text">Remove from Recents</string>
+ <string name="remove_task_button_text">Remove from Overview</string>
</resources>
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsInstrumentationTest.java b/ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsInstrumentationTest.java
similarity index 81%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsInstrumentationTest.java
rename to ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsInstrumentationTest.java
index 3c17059..3701f22 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsInstrumentationTest.java
+++ b/ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsInstrumentationTest.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.example.android.documentcentricrecents.tests;
+package com.example.android.documentcentricapps.tests;
-import com.example.android.documentcentricrecents.DocumentCentricActivity;
-import com.example.android.documentcentricrecents.R;
+import com.example.android.documentcentricapps.DocumentCentricActivity;
+import com.example.android.documentcentricapps.R;
import android.app.ActivityManager;
import android.content.Context;
@@ -29,15 +29,15 @@
import java.util.List;
/**
- * Instrumentation tests for DocumentCentricRecents sample.
+ * Instrumentation tests for DocumentCentricApps sample.
*/
@LargeTest
-public class DocumentCentricRecentsInstrumentationTest extends
+public class DocumentCentricAppsInstrumentationTest extends
ActivityInstrumentationTestCase2<DocumentCentricActivity> {
private DocumentCentricActivity mDocumentCentricActivity;
- public DocumentCentricRecentsInstrumentationTest() {
+ public DocumentCentricAppsInstrumentationTest() {
super(DocumentCentricActivity.class);
}
@@ -47,7 +47,7 @@
mDocumentCentricActivity = getActivity();
}
- public void testNewDocument_CreatesRecentsEntry() {
+ public void testNewDocument_CreatesOverviewEntry() {
// Given a initialized Activity
assertNotNull("mDocumentCentricActivity is null", mDocumentCentricActivity);
final Button createNewDocumentButton = (Button) mDocumentCentricActivity
@@ -57,7 +57,7 @@
// When "Create new Document" Button is clicked
TouchUtils.clickView(this, createNewDocumentButton);
- // Then a entry in recent app tasks is created.
+ // Then a entry in overview app tasks is created.
List<ActivityManager.AppTask> recentAppTasks = getRecentAppTasks();
assertEquals("# of recentAppTasks does not match", 2, recentAppTasks.size());
}
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsUnitTest.java b/ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsUnitTest.java
similarity index 87%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsUnitTest.java
rename to ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsUnitTest.java
index 4c13002..b3da974 100644
--- a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/tests/src/com/example/android/documentcentricrecents/tests/DocumentCentricRecentsUnitTest.java
+++ b/ui/activitytasks/DocumentCentricApps/Application/tests/src/com/example/android/documentcentricapps/tests/DocumentCentricAppsUnitTest.java
@@ -14,28 +14,26 @@
* limitations under the License.
*/
-package com.example.android.documentcentricrecents.tests;
+package com.example.android.documentcentricapps.tests;
-import com.example.android.documentcentricrecents.DocumentCentricActivity;
-import com.example.android.documentcentricrecents.R;
+import com.example.android.documentcentricapps.DocumentCentricActivity;
+import com.example.android.documentcentricapps.R;
import android.content.Intent;
import android.test.ActivityUnitTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
import android.widget.Button;
import android.widget.CheckBox;
/**
- * Unit tests for DocumentCentricRecents sample.
+ * Unit tests for DocumentCentricApps sample.
*/
@MediumTest
-public class DocumentCentricRecentsUnitTest extends ActivityUnitTestCase<DocumentCentricActivity> {
+public class DocumentCentricAppsUnitTest extends ActivityUnitTestCase<DocumentCentricActivity> {
private DocumentCentricActivity mDocumentCentricActivity;
- public DocumentCentricRecentsUnitTest() {
+ public DocumentCentricAppsUnitTest() {
super(DocumentCentricActivity.class);
}
diff --git a/ui/activitytasks/DocumentCentricApps/CONTRIB.md b/ui/activitytasks/DocumentCentricApps/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/ui/activitytasks/DocumentCentricApps/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/ui/activitytasks/DocumentCentricApps/LICENSE b/ui/activitytasks/DocumentCentricApps/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/ui/activitytasks/DocumentCentricApps/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 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.
diff --git a/ui/activitytasks/DocumentCentricRecents/build.gradle b/ui/activitytasks/DocumentCentricApps/build.gradle
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/build.gradle
rename to ui/activitytasks/DocumentCentricApps/build.gradle
diff --git a/ui/activitytasks/DocumentCentricRecents/buildSrc/build.gradle b/ui/activitytasks/DocumentCentricApps/buildSrc/build.gradle
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/buildSrc/build.gradle
rename to ui/activitytasks/DocumentCentricApps/buildSrc/build.gradle
diff --git a/ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar b/ui/activitytasks/DocumentCentricApps/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.jar
rename to ui/activitytasks/DocumentCentricApps/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.properties b/ui/activitytasks/DocumentCentricApps/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/gradle/wrapper/gradle-wrapper.properties
rename to ui/activitytasks/DocumentCentricApps/gradle/wrapper/gradle-wrapper.properties
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew b/ui/activitytasks/DocumentCentricApps/gradlew
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/gradlew
rename to ui/activitytasks/DocumentCentricApps/gradlew
diff --git a/ui/activitytasks/DocumentCentricRecents/gradlew.bat b/ui/activitytasks/DocumentCentricApps/gradlew.bat
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/gradlew.bat
rename to ui/activitytasks/DocumentCentricApps/gradlew.bat
diff --git a/ui/activitytasks/DocumentCentricApps/settings.gradle b/ui/activitytasks/DocumentCentricApps/settings.gradle
new file mode 100644
index 0000000..aa94981
--- /dev/null
+++ b/ui/activitytasks/DocumentCentricApps/settings.gradle
@@ -0,0 +1 @@
+include 'Application'
\ No newline at end of file
diff --git a/ui/activitytasks/DocumentCentricRecents/template-params.xml b/ui/activitytasks/DocumentCentricApps/template-params.xml
similarity index 81%
rename from ui/activitytasks/DocumentCentricRecents/template-params.xml
rename to ui/activitytasks/DocumentCentricApps/template-params.xml
index d83182e..589e9f1 100644
--- a/ui/activitytasks/DocumentCentricRecents/template-params.xml
+++ b/ui/activitytasks/DocumentCentricApps/template-params.xml
@@ -20,7 +20,7 @@
<sample>
<name>DocumentCentricRecents</name>
<group>UI</group>
- <package>com.example.android.documentcentricrecents</package>
+ <package>com.example.android.documentcentricapps</package>
<!-- change minSdk if needed-->
<minSdk>21</minSdk>
@@ -28,10 +28,10 @@
<strings>
<intro>
<![CDATA[
- This sample shows the basic usage of the new \"Document Centric Recents\" API.
- It let\'s you create new documents in the recents history and persists its
+ This sample shows the basic usage of the new \"Document Centric Apps\" API.
+ It let\'s you create new documents in the system overview menu and persists its
state through reboots. If \"Task per document\" is checked a new task will be
- created for every new document in recents.
+ created for every new document in the overview menu.
]]>
</intro>
</strings>
diff --git a/ui/activitytasks/DocumentCentricRecents/settings.gradle b/ui/activitytasks/DocumentCentricRecents/settings.gradle
deleted file mode 100644
index 68519b4..0000000
--- a/ui/activitytasks/DocumentCentricRecents/settings.gradle
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-include 'DocumentCentricRecentsSample'
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/.gitignore b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/.gitignore
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/.gitignore
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/.gitignore
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/proguard-project.txt b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/proguard-project.txt
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/proguard-project.txt
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/proguard-project.txt
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/AndroidManifest.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/AndroidManifest.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/AndroidManifest.xml
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/AndroidManifest.xml
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/java/com/example/android/documentcentricrelinquishidentity/NewDocumentActivity.java b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/java/com/example/android/documentcentricrelinquishidentity/NewDocumentActivity.java
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/java/com/example/android/documentcentricrelinquishidentity/NewDocumentActivity.java
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/java/com/example/android/documentcentricrelinquishidentity/NewDocumentActivity.java
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/java/com/example/android/documentcentricrelinquishidentity/RelinquishIdentityActivity.java b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/java/com/example/android/documentcentricrelinquishidentity/RelinquishIdentityActivity.java
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/java/com/example/android/documentcentricrelinquishidentity/RelinquishIdentityActivity.java
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/java/com/example/android/documentcentricrelinquishidentity/RelinquishIdentityActivity.java
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-hdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-hdpi/ic_launcher.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-hdpi/new_icon.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-hdpi/new_icon.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-hdpi/new_icon.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-hdpi/new_icon.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-mdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-mdpi/ic_launcher.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-mdpi/new_icon.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-mdpi/new_icon.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-mdpi/new_icon.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-mdpi/new_icon.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xhdpi/ic_launcher.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xhdpi/new_icon.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xhdpi/new_icon.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xhdpi/new_icon.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xhdpi/new_icon.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/drawable-xxhdpi/ic_launcher.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xxhdpi/new_icon.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xxhdpi/new_icon.png
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xxhdpi/new_icon.png
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/drawable-xxhdpi/new_icon.png
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/layout/activity_document.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/layout/activity_document.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/layout/activity_document.xml
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/layout/activity_document.xml
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/layout/activity_relinquish_identity.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/layout/activity_relinquish_identity.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/layout/activity_relinquish_identity.xml
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/layout/activity_relinquish_identity.xml
diff --git a/ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/dimens.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/values/dimens.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRecents/DocumentCentricRecentsSample/src/main/res/values/dimens.xml
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/values/dimens.xml
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/values/strings.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/values/strings.xml
similarity index 100%
rename from ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/values/strings.xml
rename to ui/activitytasks/DocumentCentricRelinquishIdentity/Application/src/main/res/values/strings.xml
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-hdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index b1efaf4..0000000
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-mdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index f5f9244..0000000
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 5d07b3f..0000000
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 6ef21e1..0000000
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/values/dimens.xml b/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/values/dimens.xml
deleted file mode 100644
index 061387a..0000000
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/DocumentCentricRelinquishIdentitySample/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright 2014 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.
- -->
-
-<resources>
- <!-- Default screen margins, per the Android Design guidelines. -->
- <dimen name="activity_horizontal_margin">16dp</dimen>
- <dimen name="activity_vertical_margin">16dp</dimen>
-</resources>
diff --git a/ui/activitytasks/DocumentCentricRelinquishIdentity/settings.gradle b/ui/activitytasks/DocumentCentricRelinquishIdentity/settings.gradle
index 7b883bf..9464a35 100644
--- a/ui/activitytasks/DocumentCentricRelinquishIdentity/settings.gradle
+++ b/ui/activitytasks/DocumentCentricRelinquishIdentity/settings.gradle
@@ -1,4 +1 @@
-
-
-
-include 'DocumentCentricRelinquishIdentitySample'
+include 'Application'
diff --git a/ui/graphics/DisplayingBitmaps/Application/src/main/AndroidManifest.xml b/ui/graphics/DisplayingBitmaps/Application/src/main/AndroidManifest.xml
index 23db308..a580277 100644
--- a/ui/graphics/DisplayingBitmaps/Application/src/main/AndroidManifest.xml
+++ b/ui/graphics/DisplayingBitmaps/Application/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/ui/holo/BorderlessButtons/Application/src/main/AndroidManifest.xml b/ui/holo/BorderlessButtons/Application/src/main/AndroidManifest.xml
index 34b2898..90b92cf 100644
--- a/ui/holo/BorderlessButtons/Application/src/main/AndroidManifest.xml
+++ b/ui/holo/BorderlessButtons/Application/src/main/AndroidManifest.xml
@@ -28,7 +28,7 @@
This sample requires API 14 for use of theme attributes such as
?android:listPreferredItemPaddingLeft.
-->
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
diff --git a/ui/lists/CustomChoiceList/Application/src/main/AndroidManifest.xml b/ui/lists/CustomChoiceList/Application/src/main/AndroidManifest.xml
index 8c194f5..8b0653e 100644
--- a/ui/lists/CustomChoiceList/Application/src/main/AndroidManifest.xml
+++ b/ui/lists/CustomChoiceList/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
diff --git a/ui/transition/BasicTransition/Application/src/main/AndroidManifest.xml b/ui/transition/BasicTransition/Application/src/main/AndroidManifest.xml
index b4698d6..435f5e0 100644
--- a/ui/transition/BasicTransition/Application/src/main/AndroidManifest.xml
+++ b/ui/transition/BasicTransition/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application
android:allowBackup="true"
diff --git a/ui/transition/CustomTransition/Application/src/main/AndroidManifest.xml b/ui/transition/CustomTransition/Application/src/main/AndroidManifest.xml
index b3328f1..010cf78 100644
--- a/ui/transition/CustomTransition/Application/src/main/AndroidManifest.xml
+++ b/ui/transition/CustomTransition/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/transition/FragmentTransition/Application/src/main/AndroidManifest.xml b/ui/transition/FragmentTransition/Application/src/main/AndroidManifest.xml
index 8d02eb0..2cfe406 100644
--- a/ui/transition/FragmentTransition/Application/src/main/AndroidManifest.xml
+++ b/ui/transition/FragmentTransition/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application
android:allowBackup="true"
diff --git a/ui/views/RecyclerView/Application/src/main/AndroidManifest.xml b/ui/views/RecyclerView/Application/src/main/AndroidManifest.xml
index b16c387..2870f1e 100644
--- a/ui/views/RecyclerView/Application/src/main/AndroidManifest.xml
+++ b/ui/views/RecyclerView/Application/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/Application/src/main/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsBasic/Application/src/main/AndroidManifest.xml
index 31cbfb8..441c3de 100644
--- a/ui/views/SlidingTabs/SlidingTabsBasic/Application/src/main/AndroidManifest.xml
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/Application/src/main/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsColors/Application/src/main/AndroidManifest.xml
index be4a43a..5ff4240 100644
--- a/ui/views/SlidingTabs/SlidingTabsColors/Application/src/main/AndroidManifest.xml
+++ b/ui/views/SlidingTabs/SlidingTabsColors/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/views/SwipeRefreshLayout/SwipeRefreshLayoutBasic/Application/src/main/AndroidManifest.xml b/ui/views/SwipeRefreshLayout/SwipeRefreshLayoutBasic/Application/src/main/AndroidManifest.xml
index fa75453..245097d 100644
--- a/ui/views/SwipeRefreshLayout/SwipeRefreshLayoutBasic/Application/src/main/AndroidManifest.xml
+++ b/ui/views/SwipeRefreshLayout/SwipeRefreshLayoutBasic/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/views/SwipeRefreshLayout/SwipeRefreshListFragment/Application/src/main/AndroidManifest.xml b/ui/views/SwipeRefreshLayout/SwipeRefreshListFragment/Application/src/main/AndroidManifest.xml
index be44930..48f1a8d 100644
--- a/ui/views/SwipeRefreshLayout/SwipeRefreshListFragment/Application/src/main/AndroidManifest.xml
+++ b/ui/views/SwipeRefreshLayout/SwipeRefreshListFragment/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/views/SwipeRefreshLayout/SwipeRefreshMultipleViews/Application/src/main/AndroidManifest.xml b/ui/views/SwipeRefreshLayout/SwipeRefreshMultipleViews/Application/src/main/AndroidManifest.xml
index aba15e0..b987db4 100644
--- a/ui/views/SwipeRefreshLayout/SwipeRefreshMultipleViews/Application/src/main/AndroidManifest.xml
+++ b/ui/views/SwipeRefreshLayout/SwipeRefreshMultipleViews/Application/src/main/AndroidManifest.xml
@@ -22,7 +22,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/window/AdvancedImmersiveMode/Application/src/main/AndroidManifest.xml b/ui/window/AdvancedImmersiveMode/Application/src/main/AndroidManifest.xml
index 1d01856..a96ebb4 100644
--- a/ui/window/AdvancedImmersiveMode/Application/src/main/AndroidManifest.xml
+++ b/ui/window/AdvancedImmersiveMode/Application/src/main/AndroidManifest.xml
@@ -27,7 +27,7 @@
<!-- This sample is to demonstrate features released in API 19.
So while it would technically run on an earlier version of Android,
there wouldn't be much point) -->
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<!-- allowBackup declares if the app can be part of device-wide backups such as "adb backup" -->
<!-- theme is a way of applying UI decisions across your entire application. You can also
define it on a per-application basis. -->
diff --git a/ui/window/BasicImmersiveMode/Application/src/main/AndroidManifest.xml b/ui/window/BasicImmersiveMode/Application/src/main/AndroidManifest.xml
index 00b4e3c..d483d5b 100644
--- a/ui/window/BasicImmersiveMode/Application/src/main/AndroidManifest.xml
+++ b/ui/window/BasicImmersiveMode/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/ui/window/ImmersiveMode/Application/src/main/AndroidManifest.xml b/ui/window/ImmersiveMode/Application/src/main/AndroidManifest.xml
index 72a60ce..b558db6 100644
--- a/ui/window/ImmersiveMode/Application/src/main/AndroidManifest.xml
+++ b/ui/window/ImmersiveMode/Application/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:allowBackup="true"
android:label="@string/app_name"
diff --git a/wearable/wear/EmbeddedApp/Application/src/main/AndroidManifest.xml b/wearable/wear/EmbeddedApp/Application/src/main/AndroidManifest.xml
index 2d266f2..77595bc 100644
--- a/wearable/wear/EmbeddedApp/Application/src/main/AndroidManifest.xml
+++ b/wearable/wear/EmbeddedApp/Application/src/main/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.embeddedapp" >
- <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="19" />
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"