init
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/* Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
import com.khronos.vulkan_samples.common.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FilterDialog extends DialogFragment {
|
||||
// The adapter that is notified by a filter changing
|
||||
private ViewPagerAdapter adapter;
|
||||
|
||||
// Saved raw filters that are used to update the adapter
|
||||
private List<String> filters;
|
||||
|
||||
// Capitalised raw filters
|
||||
private List<String> labels;
|
||||
|
||||
// Save state of the current applied filter
|
||||
// This is used to initialise the filter every time it is opened
|
||||
protected List<Boolean> values;
|
||||
|
||||
// Mutable copy of the saved state
|
||||
// This is used when a dialog is open to track the state of the labels
|
||||
// If a filter is applied values is replaced with this list; otherwise This is discarded
|
||||
protected List<Boolean> alteredValues;
|
||||
|
||||
public void setup(ViewPagerAdapter adapter, List<String> filters) {
|
||||
this.adapter = adapter;
|
||||
this.filters = new ArrayList<>(filters);
|
||||
this.labels = new ArrayList<>(filters.size());
|
||||
this.values = new ArrayList<>(filters.size());
|
||||
|
||||
// Initialise labels only once
|
||||
// Default set all filters to checked
|
||||
for (int i = 0; i < filters.size(); ++i) {
|
||||
this.labels.add(i, Utils.capitalize(filters.get(i)));
|
||||
this.values.add(i, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
// Initial labels and values for the list of filters
|
||||
final CharSequence[] labels = this.labels.toArray(new CharSequence[0]);
|
||||
boolean[] values = Utils.toBoolArray(this.values);
|
||||
|
||||
// Initiate the mutable filter list
|
||||
this.alteredValues = new ArrayList<>(this.values);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
|
||||
.setTitle("Filter Samples by Tag")
|
||||
.setMultiChoiceItems(labels, values, new FilterMultiChoiceClickListener(this))
|
||||
.setPositiveButton("Apply", new FilterClickListener(this));
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the adapter that the current applied filter has changed
|
||||
*/
|
||||
protected void notifyAdapter() {
|
||||
adapter.applyFilter(getFilter());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all raw filters that have been applied
|
||||
*
|
||||
* @return List of applied filters
|
||||
*/
|
||||
public List<String> getFilter() {
|
||||
List<String> filters = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < this.filters.size(); i++) {
|
||||
if (this.values.get(i)) {
|
||||
filters.add(this.filters.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes to a filter item's state must not persist if the dialog is closed without applying a filter.
|
||||
* Update alteredValues, changes are discarded if the filter is not applied
|
||||
*/
|
||||
class FilterMultiChoiceClickListener implements DialogInterface.OnMultiChoiceClickListener {
|
||||
private final FilterDialog dialog;
|
||||
|
||||
FilterMultiChoiceClickListener(FilterDialog dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
|
||||
if (which > this.dialog.alteredValues.size() || which < 0) {
|
||||
// Which is not in the label array - should never happen
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialog.alteredValues.set(which, isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When applying a filter override the current values and then notify the adapter that the current filter has been changed
|
||||
*/
|
||||
class FilterClickListener implements DialogInterface.OnClickListener {
|
||||
private final FilterDialog dialog;
|
||||
|
||||
FilterClickListener(FilterDialog dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
this.dialog.values = new ArrayList<>(this.dialog.alteredValues);
|
||||
this.dialog.notifyAdapter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Copyright (c) 2019-2024, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.google.androidgamesdk.GameActivity;
|
||||
import com.khronos.vulkan_samples.common.Notifications;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class NativeSampleActivity extends GameActivity {
|
||||
|
||||
private Context context;
|
||||
|
||||
private final Semaphore semaphore = new Semaphore(0, true);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle instance) {
|
||||
super.onCreate(instance);
|
||||
|
||||
Notifications.initNotificationChannel(this);
|
||||
|
||||
context = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
View decorView = getWindow().getDecorView();
|
||||
decorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Handle the application when an error is thrown and display a message
|
||||
*/
|
||||
public void fatalError(String message) {
|
||||
final NativeSampleActivity activity = this;
|
||||
|
||||
ApplicationInfo applicationInfo = activity.getApplicationInfo();
|
||||
|
||||
this.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Vulkan Samples");
|
||||
builder.setMessage(message);
|
||||
builder.setPositiveButton("Close", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
builder.setCancelable(false);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
try {
|
||||
semaphore.acquire();
|
||||
}
|
||||
catch (InterruptedException e) { }
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.khronos.vulkan_samples.model.Sample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SampleArrayAdapter extends ArrayAdapter<Sample> {
|
||||
|
||||
SampleArrayAdapter(Context context, List<Sample> sample_list) {
|
||||
super(context, R.layout.listview_item, sample_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a view for a position in the sample list
|
||||
*
|
||||
* @param position The position in the list
|
||||
* @param view The view object that was previously at this position
|
||||
* @param parent The parent view group
|
||||
* @return A view object representing a given sample at a list position
|
||||
*/
|
||||
@NonNull
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public View getView(int position, View view, @NonNull ViewGroup parent) {
|
||||
// Recycle view objects
|
||||
if (view == null) {
|
||||
view = LayoutInflater.from(getContext()).inflate(R.layout.listview_item, parent, false);
|
||||
}
|
||||
|
||||
Sample sample = getItem(position);
|
||||
assert sample != null;
|
||||
|
||||
TextView title = view.findViewById(R.id.title_text);
|
||||
title.setText(sample.getName());
|
||||
|
||||
TextView description = view.findViewById(R.id.description_text);
|
||||
description.setText(sample.getDescription());
|
||||
|
||||
TextView vendorTag = view.findViewById(R.id.vendor_text);
|
||||
vendorTag.setText(sample.getTagText());
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/* Copyright (c) 2019-2024, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.khronos.vulkan_samples.common.Notifications;
|
||||
import com.khronos.vulkan_samples.model.Permission;
|
||||
import com.khronos.vulkan_samples.model.Sample;
|
||||
import com.khronos.vulkan_samples.model.SampleStore;
|
||||
import com.khronos.vulkan_samples.views.PermissionView;
|
||||
import com.khronos.vulkan_samples.views.SampleListView;
|
||||
|
||||
public class SampleLauncherActivity extends AppCompatActivity {
|
||||
|
||||
SampleListView sampleListView;
|
||||
PermissionView permissionView;
|
||||
|
||||
private boolean isBenchmarkMode = false;
|
||||
private boolean isHeadless = false;
|
||||
|
||||
public SampleStore samples;
|
||||
|
||||
// Required sample permissions
|
||||
List<Permission> permissions;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if (loadNativeLibrary(getResources().getString(R.string.native_lib_name))) {
|
||||
// Get sample info from cpp cmake generated file
|
||||
samples = new SampleStore(Arrays.asList(getSamples()));
|
||||
}
|
||||
|
||||
// Required Permissions
|
||||
permissions = new ArrayList<>();
|
||||
|
||||
if (checkPermissions()) {
|
||||
// Permissions previously granted skip requesting them
|
||||
parseArguments();
|
||||
showSamples();
|
||||
} else {
|
||||
// Chain request permissions
|
||||
requestNextPermission();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.main_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
MenuItem checkable = menu.findItem(R.id.menu_benchmark_mode);
|
||||
checkable.setChecked(isBenchmarkMode);
|
||||
|
||||
checkable = menu.findItem(R.id.menu_headless);
|
||||
checkable.setChecked(isHeadless);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if(item.getItemId() == R.id.filter_button) {
|
||||
sampleListView.dialog.show(getSupportFragmentManager(), "filter");
|
||||
return true;
|
||||
} else if(item.getItemId() == R.id.menu_run_samples) {
|
||||
String category = "";
|
||||
ViewPagerAdapter adapter = ((ViewPagerAdapter) sampleListView.viewPager.getAdapter());
|
||||
if (adapter != null) {
|
||||
category = adapter.getCurrentFragment().getCategory();
|
||||
}
|
||||
|
||||
List<String> arguments = new ArrayList<>();
|
||||
arguments.add("batch");
|
||||
arguments.add("--category");
|
||||
arguments.add(category);
|
||||
arguments.add("--tag");
|
||||
arguments.addAll(sampleListView.dialog.getFilter());
|
||||
|
||||
String[] sa = {};
|
||||
launchWithCommandArguments(arguments.toArray(sa));
|
||||
return true;
|
||||
} else if(item.getItemId() == R.id.menu_benchmark_mode) {
|
||||
isBenchmarkMode = !item.isChecked();
|
||||
item.setChecked(isBenchmarkMode);
|
||||
return true;
|
||||
} else if(item.getItemId() == R.id.menu_headless) {
|
||||
isHeadless = !item.isChecked();
|
||||
item.setChecked(isHeadless);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
requestNextPermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a native library
|
||||
*
|
||||
* @param native_lib_name Native library to load
|
||||
* @return True if loaded correctly; False otherwise
|
||||
*/
|
||||
private boolean loadNativeLibrary(String native_lib_name) {
|
||||
boolean status = true;
|
||||
|
||||
try {
|
||||
System.loadLibrary(native_lib_name);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Toast.makeText(getApplicationContext(), "Native code library failed to load.", Toast.LENGTH_SHORT).show();
|
||||
|
||||
status = false;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain request permissions from the required permission list. When called the
|
||||
* next unrequested permission with be requested If all permission are requested
|
||||
* but not all granted; requested states will be reset and the PermissionView
|
||||
* will be shown
|
||||
*/
|
||||
public void requestNextPermission() {
|
||||
boolean granted = true;
|
||||
|
||||
for (Permission permission : permissions) {
|
||||
|
||||
// Permission previously requested but not granted
|
||||
if (!permission.granted(getApplication())) {
|
||||
// Permission not previously requested - request it
|
||||
if (!permission.isRequested()) {
|
||||
permission.request(this);
|
||||
return;
|
||||
}
|
||||
|
||||
granted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (granted) {
|
||||
parseArguments();
|
||||
showSamples();
|
||||
} else {
|
||||
// Reset all permissions request state so they can be requested again
|
||||
for (Permission permission : permissions) {
|
||||
permission.setRequested(false);
|
||||
}
|
||||
showPermissionsMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all required permissions have been granted
|
||||
*
|
||||
* @return True if all granted; False otherwise
|
||||
*/
|
||||
public boolean checkPermissions() {
|
||||
for (Permission permission : permissions) {
|
||||
if (!permission.granted(getApplicationContext())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/Create the Permission View. Hides all other views
|
||||
*/
|
||||
public void showPermissionsMessage() {
|
||||
if (permissionView == null) {
|
||||
permissionView = new PermissionView(this);
|
||||
}
|
||||
|
||||
if (sampleListView != null) {
|
||||
sampleListView.hide();
|
||||
}
|
||||
|
||||
permissionView.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/Create the Sample View. Hides all other views
|
||||
*/
|
||||
public void showSamples() {
|
||||
if (sampleListView == null) {
|
||||
sampleListView = new SampleListView(this);
|
||||
}
|
||||
|
||||
if (permissionView != null) {
|
||||
permissionView.hide();
|
||||
}
|
||||
|
||||
sampleListView.show();
|
||||
}
|
||||
|
||||
// Allow Orientation locking for testing
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
public void parseArguments() {
|
||||
// Handle argument passing
|
||||
Bundle extras = this.getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
if (extras.containsKey("cmd")) {
|
||||
String[] commands = null;
|
||||
String[] command_arguments = extras.getStringArray("cmd");
|
||||
String command = extras.getString("cmd");
|
||||
if (command_arguments != null) {
|
||||
commands = command_arguments;
|
||||
} else if (command != null) {
|
||||
commands = command.split("[ ]+");
|
||||
}
|
||||
|
||||
if (commands != null) {
|
||||
for (String cmd : commands) {
|
||||
if (cmd.equals("test")) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
launchWithCommandArguments(commands);
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
} else if (extras.containsKey("sample")) {
|
||||
launchSample(extras.getString("sample"));
|
||||
finishAffinity();
|
||||
} else if (extras.containsKey("test")) {
|
||||
launchTest(extras.getString("test"));
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set arguments of the Native Activity You may also use a String[]
|
||||
*
|
||||
* @param args A string array of arguments
|
||||
*/
|
||||
public void setArguments(String... args) {
|
||||
List<String> arguments = new ArrayList<>(Arrays.asList(args));
|
||||
if (isBenchmarkMode) {
|
||||
arguments.add("--benchmark");
|
||||
}
|
||||
if (isHeadless) {
|
||||
arguments.add("--headless_surface");
|
||||
}
|
||||
String[] argArray = new String[arguments.size()];
|
||||
sendArgumentsToPlatform(arguments.toArray(argArray));
|
||||
}
|
||||
|
||||
public void launchWithCommandArguments(String... args) {
|
||||
setArguments(args);
|
||||
Intent intent = new Intent(SampleLauncherActivity.this, NativeSampleActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void launchTest(String testID) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
launchWithCommandArguments("test", testID);
|
||||
}
|
||||
|
||||
public void launchSample(String sampleID) {
|
||||
Sample sample = samples.findByID(sampleID);
|
||||
if (sample == null) {
|
||||
Notifications.toast(this, "Could not find sample " + sampleID);
|
||||
showSamples();
|
||||
return;
|
||||
}
|
||||
launchWithCommandArguments("sample", sampleID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get samples from the Native Application
|
||||
*
|
||||
* @return A list of Samples that are currently installed in the Native
|
||||
* Application
|
||||
*/
|
||||
private native Sample[] getSamples();
|
||||
|
||||
/**
|
||||
* Set the arguments of the Native Application
|
||||
*
|
||||
* @param args The arguments that are to be passed to the app
|
||||
*/
|
||||
private native void sendArgumentsToPlatform(String[] args);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.khronos.vulkan_samples.model.Sample;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TabFragment extends Fragment {
|
||||
|
||||
private String category;
|
||||
|
||||
private List<Sample> sampleList = new ArrayList<>();
|
||||
|
||||
private AdapterView.OnItemClickListener clickListener;
|
||||
|
||||
/**
|
||||
* Create a new Tab Fragment Instance
|
||||
*
|
||||
* @param category The Title of the TabFragment
|
||||
* @param sampleList The Samples that this tab will render
|
||||
* @param clickListener The listener used when a item is clicked
|
||||
* @return A new Tab Fragment
|
||||
*/
|
||||
public static Fragment getInstance(String category, List<Sample> sampleList, AdapterView.OnItemClickListener clickListener) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("category", category);
|
||||
TabFragment tabFragment = new TabFragment();
|
||||
tabFragment.setArguments(bundle);
|
||||
tabFragment.setSampleList(sampleList);
|
||||
tabFragment.setClickListener(clickListener);
|
||||
return tabFragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sample list that the fragment should render
|
||||
*
|
||||
* @param list A list of samples
|
||||
*/
|
||||
public void setSampleList(List<Sample> list) {
|
||||
this.sampleList = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the action to perform when a sample list item is clicked
|
||||
*
|
||||
* @param clickListener A OnItemClickListener
|
||||
*/
|
||||
public void setClickListener(AdapterView.OnItemClickListener clickListener) {
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
assert getArguments() != null;
|
||||
category = getArguments().getString("category");
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_tab, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
ListView listView = view.findViewById(R.id.sample_list);
|
||||
SampleArrayAdapter sampleArrayAdapter = new SampleArrayAdapter(view.getContext(), sampleList);
|
||||
listView.setAdapter(sampleArrayAdapter);
|
||||
listView.setOnItemClickListener(this.clickListener);
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import com.khronos.vulkan_samples.model.Sample;
|
||||
import com.khronos.vulkan_samples.model.SampleStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
|
||||
private TabFragment currentFragment;
|
||||
|
||||
private List<Sample> viewableSamples = new ArrayList<>();
|
||||
|
||||
private final SampleStore samples;
|
||||
|
||||
private final AdapterView.OnItemClickListener clickListener;
|
||||
|
||||
public ViewPagerAdapter(FragmentManager manager, SampleStore samples, AdapterView.OnItemClickListener clickListener) {
|
||||
super(manager);
|
||||
this.samples = samples;
|
||||
this.clickListener = clickListener;
|
||||
applyFilter(samples.getTags());
|
||||
}
|
||||
|
||||
public void setDialog(FilterDialog dialog) {
|
||||
dialog.setup(this, samples.getTags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the filter so that the viewableSamples updates
|
||||
*/
|
||||
public void applyFilter(List<String> filterTags) {
|
||||
viewableSamples = new ArrayList<>(samples.getByTags(filterTags));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
List<Sample> fragmentSamples = new ArrayList<>();
|
||||
|
||||
String category = samples.getCategories().get(position);
|
||||
assert category != null;
|
||||
|
||||
for (Sample sample : Objects.requireNonNull(samples.getByCategory(category))) {
|
||||
for (Sample viewableSample : this.viewableSamples) {
|
||||
if (sample.equals(viewableSample)) {
|
||||
fragmentSamples.add(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TabFragment.getInstance(category, fragmentSamples, clickListener);
|
||||
}
|
||||
|
||||
public int getItemPosition(@NonNull Object object) {
|
||||
return POSITION_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
if (getCurrentFragment() != object) {
|
||||
currentFragment = (TabFragment) object;
|
||||
}
|
||||
super.setPrimaryItem(container, position, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return samples.getCategoryIndex().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return samples.getCategories().get(position);
|
||||
}
|
||||
|
||||
TabFragment getCurrentFragment() {
|
||||
return currentFragment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/* Copyright (c) 2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.common;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import android.widget.Toast;
|
||||
import android.content.Context;
|
||||
|
||||
import com.khronos.vulkan_samples.R;
|
||||
|
||||
public class Notifications {
|
||||
private static final String NOTIFICATION_PREFS = "NOTIFICATION_PREFS";
|
||||
private static final String NOTIFICATION_KEY = "NOTIFICATION_KEY";
|
||||
public static final String CHANNEL_ID = "vkb";
|
||||
|
||||
private static int initialId = 0;
|
||||
|
||||
public static void initNotificationChannel(Context context) {
|
||||
// Create Notification Channel API 26+
|
||||
//
|
||||
// API 26+ implements notifications using a channel where notifications are submitted to channel
|
||||
// The following initialises the channel used by vkb to push notifications to.
|
||||
// IMPORTANCE_HIGH = push notifications
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_name), NotificationManager.IMPORTANCE_HIGH);
|
||||
channel.setDescription(context.getString(R.string.channel_desc));
|
||||
NotificationManager nm = context.getSystemService(NotificationManager.class);
|
||||
nm.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getNotificationId(Context context) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(NOTIFICATION_PREFS, Context.MODE_PRIVATE);
|
||||
int id = initialId;
|
||||
if (prefs.contains(NOTIFICATION_KEY)) {
|
||||
id = prefs.getInt(NOTIFICATION_KEY, initialId);
|
||||
}
|
||||
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putInt(NOTIFICATION_KEY, id + 1);
|
||||
editor.apply();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a push notification from JNI with a message
|
||||
*
|
||||
* @param message A string of a message to be shown
|
||||
*/
|
||||
public static void notification(Context context, final String message) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.icon)
|
||||
.setContentTitle("Vulkan Samples Error")
|
||||
.setContentText(message)
|
||||
.setStyle(new NotificationCompat.BigTextStyle()
|
||||
.bigText(message))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||
|
||||
NotificationManagerCompat nm = NotificationManagerCompat.from(context);
|
||||
nm.notify(getNotificationId(context), builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a toast from JNI on the android main UI thread with a message
|
||||
*
|
||||
* @param message A string of a message to be shown
|
||||
*/
|
||||
public static void toast(final Context context, final String message) {
|
||||
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, message, Toast.LENGTH_LONG).show());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class Utils {
|
||||
/**
|
||||
* A helper to capitalize a string
|
||||
*
|
||||
* @param str The string to be capitalized
|
||||
* @return A capitalized string
|
||||
*/
|
||||
public static String capitalize(String str) {
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert List of Boolean to primitive boolean array
|
||||
* @param list The list to be converted
|
||||
* @return A primitive boolean array containing the lists values
|
||||
*/
|
||||
public static boolean[] toBoolArray(List<Boolean> list) {
|
||||
boolean[] booleans = new boolean[list.size()];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
booleans[i] = list.get(i);
|
||||
}
|
||||
return booleans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert List of String to String array
|
||||
* @param list The list to be converted
|
||||
* @return A String array containing the lists values
|
||||
*/
|
||||
public static String[] toStringArray(List<String> list) {
|
||||
String[] strings = new String[list.size()];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
strings[i] = list.get(i);
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator orders with a predefined list
|
||||
*/
|
||||
public static class PredefinedOrderComparator implements Comparator<String> {
|
||||
private final List<String> defined_order;
|
||||
|
||||
public PredefinedOrderComparator(String... predefined_order) {
|
||||
defined_order = Collections.unmodifiableList(Arrays.asList(predefined_order));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
// Remove duplicates
|
||||
if (o1.equals(o2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret;
|
||||
int o1_order = defined_order.indexOf(o1);
|
||||
int o2_order = defined_order.indexOf(o2);
|
||||
|
||||
//if neither are found in the order list, then do natural sort - string comparison
|
||||
if (o1_order < 0 && o2_order < 0) ret = o1.compareTo(o2);
|
||||
|
||||
//if only one is found in the order list, float it above the other
|
||||
else if (o1_order < 0) ret = 1;
|
||||
else if (o2_order < 0) ret = -1;
|
||||
|
||||
//if both are found in the order list, then do the index comparision
|
||||
else ret = o1_order - o2_order;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.model;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class Permission {
|
||||
private final String name;
|
||||
private final int code;
|
||||
private boolean requested = false;
|
||||
|
||||
public Permission(String name, int code) {
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the requested state of the permission
|
||||
*
|
||||
* @param requested The desired requested state
|
||||
*/
|
||||
public void setRequested(boolean requested) {
|
||||
this.requested = requested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if the permission has already been requested
|
||||
*
|
||||
* @return True if previously requested; false otherwise
|
||||
*/
|
||||
public boolean isRequested() {
|
||||
return requested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the permission
|
||||
*
|
||||
* @return The permissions name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code of the permission
|
||||
*
|
||||
* @return The permissions code
|
||||
*/
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query whether the permission has been granted for the App
|
||||
*
|
||||
* @param ctx The activity context that needs to be queried for the permission
|
||||
* @return True if permission granted; false otherwise
|
||||
*/
|
||||
public boolean granted(Context ctx) {
|
||||
return ContextCompat.checkSelfPermission(ctx, name) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the permission for a given Activity
|
||||
*
|
||||
* @param activity Activity to request the permission for
|
||||
*/
|
||||
public void request(Activity activity) {
|
||||
ActivityCompat.requestPermissions(activity, new String[]{name}, code);
|
||||
requested = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/* Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.model;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.khronos.vulkan_samples.common.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Sample implements Comparable<Sample> {
|
||||
private final String id;
|
||||
private final String category;
|
||||
private final String author;
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private String tagText;
|
||||
private final List<String> tags;
|
||||
|
||||
public Sample(String id, String category, String author, String name, String description, String[] tags) {
|
||||
this.id = id;
|
||||
this.category = category;
|
||||
this.author = author;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
|
||||
this.tags = new LinkedList<>(Arrays.asList(tags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the Tag Text that is shown in the sample list
|
||||
*
|
||||
* @return A concatenated string of a samples tags
|
||||
*/
|
||||
private String generateTagText() {
|
||||
List<String> formatted_tags = new ArrayList<>(this.tags.size());
|
||||
|
||||
for (String tag : this.tags) {
|
||||
formatted_tags.add(Utils.capitalize(tag));
|
||||
}
|
||||
|
||||
// If the sample has a tag other than "Any" then "Any" can be removed
|
||||
if (formatted_tags.size() > 1) {
|
||||
formatted_tags.remove("Any");
|
||||
}
|
||||
|
||||
return TextUtils.join(", ", formatted_tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Sample's ID
|
||||
*
|
||||
* @return A Sample ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's category
|
||||
*
|
||||
* @return The sample's category
|
||||
*/
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's author
|
||||
*
|
||||
* @return The sample's author
|
||||
*/
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's name
|
||||
*
|
||||
* @return The sample's name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's description
|
||||
*
|
||||
* @return The sample's description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's tags
|
||||
*
|
||||
* @return The sample's tags
|
||||
*/
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample's tag text
|
||||
*
|
||||
* @return The sample's tag text
|
||||
*/
|
||||
public String getTagText() {
|
||||
if (tagText == null) {
|
||||
tagText = generateTagText();
|
||||
}
|
||||
return tagText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two samples are equal
|
||||
* Can be used with a HashMap
|
||||
*
|
||||
* @return True if samples are equal; false otherwise
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (object instanceof Sample) {
|
||||
Sample sample = (Sample) object;
|
||||
return this.id.equals(sample.id);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when comparing two samples - Alphabetical Case Insensitive
|
||||
* Sample id's are unique so this is used to compare
|
||||
*
|
||||
* @param sample To compare too
|
||||
* @return - if less, 0 if equal + if greater than
|
||||
*/
|
||||
public int compareTo(Sample sample) {
|
||||
return sample.id.compareToIgnoreCase(this.id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/* Copyright (c) 2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.model;
|
||||
|
||||
import com.khronos.vulkan_samples.common.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A one stop store of samples that are pre indexed for use in the App
|
||||
*/
|
||||
public class SampleStore {
|
||||
private final Set<Sample> samples = new TreeSet<>();
|
||||
|
||||
private final Set<String> categories = new TreeSet<>(new Utils.PredefinedOrderComparator("api", "performance", "extensions"));
|
||||
private final Map<String, List<Sample>> categoryIndex = new HashMap<>();
|
||||
|
||||
private final Set<String> tags = new TreeSet<>(new Utils.PredefinedOrderComparator("any"));
|
||||
private final Map<String, List<Sample>> tagIndex = new HashMap<>();
|
||||
|
||||
public SampleStore(List<Sample> samples) {
|
||||
if (samples == null) {
|
||||
samples = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Index all samples by tag and by category
|
||||
for (Sample sample : samples) {
|
||||
if (sample == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.samples.add(sample);
|
||||
|
||||
if (!categoryIndex.containsKey(sample.getCategory())) {
|
||||
categoryIndex.put(sample.getCategory(), new ArrayList<>());
|
||||
}
|
||||
|
||||
List<Sample> category = categoryIndex.get(sample.getCategory());
|
||||
if (category != null) {
|
||||
category.add(sample);
|
||||
}
|
||||
|
||||
for (String tag : sample.getTags()) {
|
||||
if (!tagIndex.containsKey(tag)) {
|
||||
tagIndex.put(tag, new ArrayList<>());
|
||||
}
|
||||
|
||||
List<Sample> index = tagIndex.get(tag);
|
||||
if (index != null) {
|
||||
index.add(sample);
|
||||
}
|
||||
|
||||
this.tags.add(tag);
|
||||
}
|
||||
|
||||
this.categories.add(sample.getCategory());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a sample by its id
|
||||
*
|
||||
* @param id of a given sample
|
||||
* @return A sample if it is found
|
||||
*/
|
||||
public Sample findByID(String id) {
|
||||
for (Sample sample : samples) {
|
||||
if (sample.getId().equals(id)) {
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category index
|
||||
*
|
||||
* @return A map of category to samples
|
||||
*/
|
||||
public Map<String, List<Sample>> getCategoryIndex() {
|
||||
return this.categoryIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all category names
|
||||
*
|
||||
* @return A list of category names
|
||||
*/
|
||||
public List<String> getCategories() {
|
||||
return new ArrayList<>(this.categories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all tag names
|
||||
*
|
||||
* @return A list of tag names
|
||||
*/
|
||||
public List<String> getTags() {
|
||||
return new ArrayList<>(this.tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sample by tag name
|
||||
*
|
||||
* @return A list of samples
|
||||
*/
|
||||
public List<Sample> getByTag(String tag) {
|
||||
return this.tagIndex.get(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sample by multiple tag names
|
||||
*
|
||||
* @return A list of samples
|
||||
*/
|
||||
public List<Sample> getByTags(List<String> tags) {
|
||||
Set<Sample> samples = new HashSet<>();
|
||||
|
||||
for (String tag : tags) {
|
||||
Collection<Sample> samplesByTag = getByTag(tag);
|
||||
if (samplesByTag != null) {
|
||||
samples.addAll(samplesByTag);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sample by category name
|
||||
*
|
||||
* @return A list of samples
|
||||
*/
|
||||
public List<Sample> getByCategory(String category) {
|
||||
return this.categoryIndex.get(category);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* Copyright (c) 2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.views;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.khronos.vulkan_samples.R;
|
||||
import com.khronos.vulkan_samples.SampleLauncherActivity;
|
||||
|
||||
/**
|
||||
* A container for all elements related to the permission view
|
||||
*/
|
||||
public class PermissionView {
|
||||
private final Button buttonPermissions;
|
||||
private final TextView textPermissions;
|
||||
|
||||
public PermissionView(SampleLauncherActivity activity) {
|
||||
buttonPermissions = activity.findViewById(R.id.button_permissions);
|
||||
buttonPermissions.setOnClickListener(new CheckPermissionClickListener(activity));
|
||||
textPermissions = activity.findViewById(R.id.text_permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the permission view
|
||||
*/
|
||||
public void show() {
|
||||
buttonPermissions.setVisibility(View.VISIBLE);
|
||||
textPermissions.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the permission view
|
||||
*/
|
||||
public void hide() {
|
||||
buttonPermissions.setVisibility(View.INVISIBLE);
|
||||
textPermissions.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Click listener for the Permission View button
|
||||
*/
|
||||
class CheckPermissionClickListener implements View.OnClickListener {
|
||||
private final SampleLauncherActivity activity;
|
||||
|
||||
CheckPermissionClickListener(SampleLauncherActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
activity.requestNextPermission();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* Copyright (c) 2020-2021, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.khronos.vulkan_samples.views;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import com.khronos.vulkan_samples.FilterDialog;
|
||||
import com.khronos.vulkan_samples.R;
|
||||
import com.khronos.vulkan_samples.SampleLauncherActivity;
|
||||
import com.khronos.vulkan_samples.ViewPagerAdapter;
|
||||
import com.khronos.vulkan_samples.model.Sample;
|
||||
|
||||
/**
|
||||
* A container for all elements related to the sample view
|
||||
*/
|
||||
public class SampleListView {
|
||||
private final TabLayout tabLayout;
|
||||
public ViewPager viewPager;
|
||||
public FilterDialog dialog;
|
||||
|
||||
public SampleListView(SampleLauncherActivity activity) {
|
||||
viewPager = activity.findViewById(R.id.viewpager);
|
||||
ViewPagerAdapter adapter = new ViewPagerAdapter(activity.getSupportFragmentManager(), activity.samples, new SampleItemClickListener(activity));
|
||||
viewPager.setAdapter(adapter);
|
||||
|
||||
dialog = new FilterDialog();
|
||||
adapter.setDialog(dialog);
|
||||
|
||||
tabLayout = activity.findViewById(R.id.tabs);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the sample view
|
||||
*/
|
||||
public void show() {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
viewPager.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the sample view
|
||||
*/
|
||||
public void hide() {
|
||||
tabLayout.setVisibility(View.INVISIBLE);
|
||||
viewPager.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Click listener for a Sample List Item
|
||||
* Start the Native Activity for the clicked Sample
|
||||
*/
|
||||
class SampleItemClickListener implements AdapterView.OnItemClickListener {
|
||||
private final SampleLauncherActivity activity;
|
||||
|
||||
SampleItemClickListener(SampleLauncherActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
String sampleID = ((Sample) parent.getItemAtPosition(position)).getId();
|
||||
activity.launchSample(sampleID);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user