summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
authorJoey <joey@lineageos.org>2019-01-23 17:49:25 +0100
committerBruno Martins <bgcngm@gmail.com>2019-01-26 23:53:25 +0100
commit26258e1bf1d578d297f3a1adf95034617caccad3 (patch)
tree0c8ae1fe505974b276c0d3173a38163c29b12800 /src/com/android/launcher3
parent35f4a332c7399938f2766a76c7285c3daef1b195 (diff)
downloadandroid_packages_apps_Trebuchet-26258e1bf1d578d297f3a1adf95034617caccad3.tar.gz
android_packages_apps_Trebuchet-26258e1bf1d578d297f3a1adf95034617caccad3.tar.bz2
android_packages_apps_Trebuchet-26258e1bf1d578d297f3a1adf95034617caccad3.zip
Trebuchet: implement hidden apps
Signed-off-by: Joey <joey@lineageos.org> Signed-off-by: Luca Stefani <luca.stefani.ge1@gmail.com> Change-Id: I10c35407820373a1d5f84b237ac449398e076dcd
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/SettingsActivity.java12
-rw-r--r--src/com/android/launcher3/lineage/hidden/HiddenAppsActivity.java155
-rw-r--r--src/com/android/launcher3/lineage/hidden/HiddenAppsAdapter.java154
-rw-r--r--src/com/android/launcher3/lineage/hidden/HiddenAppsFilter.java40
-rw-r--r--src/com/android/launcher3/lineage/hidden/LoadHiddenComponentsTask.java102
-rw-r--r--src/com/android/launcher3/lineage/hidden/UpdateItemVisibilityTask.java62
-rw-r--r--src/com/android/launcher3/lineage/hidden/db/HiddenComponent.java73
-rw-r--r--src/com/android/launcher3/lineage/hidden/db/HiddenDatabaseHelper.java119
8 files changed, 717 insertions, 0 deletions
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index c055c130f..bbb3eeff6 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -54,6 +54,7 @@ import android.widget.NumberPicker;
import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.lineage.LineageLauncherCallbacks;
import com.android.launcher3.lineage.LineageUtils;
+import com.android.launcher3.lineage.hidden.HiddenAppsActivity;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.ListViewHighlighter;
import com.android.launcher3.util.SettingsObserver;
@@ -132,6 +133,8 @@ public class SettingsActivity extends Activity {
PreferenceCategory homeGroup = (PreferenceCategory)
findPreference("category_home");
+ PreferenceCategory drawerGroup = (PreferenceCategory)
+ findPreference("category_drawer");
PreferenceCategory iconGroup = (PreferenceCategory)
findPreference("category_icons");
@@ -186,6 +189,15 @@ public class SettingsActivity extends Activity {
mGridPref.setSummary(mPrefs.getString(KEY_GRID_SIZE, getDefaultGridSize()));
}
+
+ Preference hiddenApps = drawerGroup.findPreference("pref_hidden_apps");
+ if (hiddenApps != null) {
+ hiddenApps.setOnPreferenceClickListener(preference -> {
+ Intent intent = new Intent(getActivity(), HiddenAppsActivity.class);
+ startActivity(intent);
+ return true;
+ });
+ }
}
@Override
diff --git a/src/com/android/launcher3/lineage/hidden/HiddenAppsActivity.java b/src/com/android/launcher3/lineage/hidden/HiddenAppsActivity.java
new file mode 100644
index 000000000..bd7056417
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/HiddenAppsActivity.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.lineage.hidden.db.HiddenComponent;
+import com.android.launcher3.lineage.hidden.db.HiddenDatabaseHelper;
+
+import java.util.List;
+
+public class HiddenAppsActivity extends Activity implements
+ HiddenAppsAdapter.Listener,
+ LoadHiddenComponentsTask.Callback,
+ UpdateItemVisibilityTask.UpdateCallback {
+ private static final int REQUEST_AUTH_CODE = 92;
+
+ private RecyclerView mRecyclerView;
+ private LinearLayout mLoadingView;
+ private ProgressBar mProgressBar;
+
+ private HiddenDatabaseHelper mDbHelper;
+ private HiddenAppsAdapter mAdapter;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstance) {
+ super.onCreate(savedInstance);
+
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ setContentView(R.layout.activity_hidden_apps);
+ mRecyclerView = findViewById(R.id.hidden_apps_list);
+ mLoadingView = findViewById(R.id.hidden_apps_loading);
+ mProgressBar = findViewById(R.id.hidden_apps_progress_bar);
+
+ mAdapter = new HiddenAppsAdapter(this);
+ mDbHelper = HiddenDatabaseHelper.getInstance(this);
+
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ mRecyclerView.setAdapter(mAdapter);
+
+ authenticate();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_AUTH_CODE) {
+ if (resultCode == Activity.RESULT_OK) {
+ showUi();
+ } else {
+ finish();
+ }
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onItemChanged(@NonNull HiddenComponent component) {
+ new UpdateItemVisibilityTask(mDbHelper, this).execute(component);
+ }
+
+ @Override
+ public void onUpdated(boolean result) {
+ LauncherAppState state = LauncherAppState.getInstanceNoCreate();
+ if (state != null) {
+ state.getModel().forceReload();
+ }
+ }
+
+ @Override
+ public void onLoadListProgress(int progress) {
+ mProgressBar.setProgress(progress);
+ }
+
+ @Override
+ public void onLoadCompleted(List<HiddenComponent> result) {
+ mLoadingView.setVisibility(View.GONE);
+ mRecyclerView.setVisibility(View.VISIBLE);
+ mAdapter.update(result);
+ }
+
+ private void authenticate() {
+ KeyguardManager manager = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ?
+ getSystemService(KeyguardManager.class) :
+ (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ if (manager == null) {
+ throw new NullPointerException("No KeyguardManager found!");
+ }
+
+ String title = getString(R.string.hidden_apps_manager_name);
+ String message = getString(R.string.hidden_apps_auth_manager);
+ Intent intent = manager.createConfirmDeviceCredentialIntent(title, message);
+
+ if (intent != null) {
+ startActivityForResult(intent, REQUEST_AUTH_CODE);
+ return;
+ }
+
+ Toast.makeText(this, R.string.hidden_apps_no_lock_error,
+ Toast.LENGTH_LONG).show();
+ finish();
+ }
+
+ private void showUi() {
+ mLoadingView.setVisibility(View.VISIBLE);
+
+ new LoadHiddenComponentsTask(mDbHelper, getPackageManager(), this).execute();
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/HiddenAppsAdapter.java b/src/com/android/launcher3/lineage/hidden/HiddenAppsAdapter.java
new file mode 100644
index 000000000..acb07ee90
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/HiddenAppsAdapter.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden;
+
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.v7.util.DiffUtil;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.launcher3.R;
+import com.android.launcher3.lineage.hidden.db.HiddenComponent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class HiddenAppsAdapter extends RecyclerView.Adapter<HiddenAppsAdapter.ViewHolder> {
+ private List<HiddenComponent> mList = new ArrayList<>();
+ private Listener mListener;
+
+ HiddenAppsAdapter(Listener listener) {
+ mListener = listener;
+ }
+
+ public void update(List<HiddenComponent> list) {
+ DiffUtil.DiffResult result = DiffUtil.calculateDiff(new Callback(mList, list));
+ mList = list;
+ result.dispatchUpdatesTo(this);
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int type) {
+ return new ViewHolder(LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.item_hidden_app, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
+ viewHolder.bind(mList.get(i));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mList.size();
+ }
+
+ public interface Listener {
+ void onItemChanged(@NonNull HiddenComponent component);
+ }
+
+ class ViewHolder extends RecyclerView.ViewHolder {
+ private ImageView mIconView;
+ private TextView mLabelView;
+ private ImageView mLockView;
+
+ ViewHolder(@NonNull View itemView) {
+ super(itemView);
+
+ mIconView = itemView.findViewById(R.id.item_hidden_app_icon);
+ mLabelView = itemView.findViewById(R.id.item_hidden_app_title);
+ mLockView = itemView.findViewById(R.id.item_hidden_app_switch);
+ }
+
+ void bind(HiddenComponent component) {
+ mIconView.setImageDrawable(component.getIcon());
+ mLabelView.setText(component.getLabel());
+ mLockView.setImageResource(component.isHidden() ?
+ R.drawable.ic_hidden_locked : R.drawable.ic_hidden_unlocked);
+
+ itemView.setOnClickListener(v -> {
+ component.invertVisibility();
+
+ mLockView.setImageResource(component.isHidden() ?
+ R.drawable.avd_hidden_lock : R.drawable.avd_hidden_unlock);
+ AnimatedVectorDrawable avd = (AnimatedVectorDrawable) mLockView.getDrawable();
+
+ int position = getAdapterPosition();
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+ avd.registerAnimationCallback(new Animatable2.AnimationCallback() {
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ updateList(position, component);
+ }
+ });
+ avd.start();
+ } else {
+ avd.start();
+ updateList(position, component);
+ }
+ });
+ }
+
+ private void updateList(int position, HiddenComponent component) {
+ mListener.onItemChanged(component);
+ mList.set(position, component);
+ notifyItemChanged(position);
+ }
+ }
+
+ private static class Callback extends DiffUtil.Callback {
+ List<HiddenComponent> mOldList;
+ List<HiddenComponent> mNewList;
+
+ public Callback(List<HiddenComponent> oldList,
+ List<HiddenComponent> newList) {
+ mOldList = oldList;
+ mNewList = newList;
+ }
+
+
+ @Override
+ public int getOldListSize() {
+ return mOldList.size();
+ }
+
+ @Override
+ public int getNewListSize() {
+ return mNewList.size();
+ }
+
+ @Override
+ public boolean areItemsTheSame(int iOld, int iNew) {
+ String oldPkg = mOldList.get(iOld).getPackageName();
+ String newPkg = mNewList.get(iNew).getPackageName();
+ return oldPkg.equals(newPkg);
+ }
+
+ @Override
+ public boolean areContentsTheSame(int iOld, int iNew) {
+ return mOldList.get(iOld).equals(mNewList.get(iNew));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/HiddenAppsFilter.java b/src/com/android/launcher3/lineage/hidden/HiddenAppsFilter.java
new file mode 100644
index 000000000..47274f73e
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/HiddenAppsFilter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden;
+
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.launcher3.AppFilter;
+import com.android.launcher3.lineage.hidden.db.HiddenDatabaseHelper;
+
+@SuppressWarnings("unused")
+public class HiddenAppsFilter extends AppFilter {
+ private HiddenDatabaseHelper mDbHelper;
+
+ public HiddenAppsFilter(Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("Context must not be null!");
+ }
+
+ mDbHelper = HiddenDatabaseHelper.getInstance(context);
+ }
+
+ @Override
+ public boolean shouldShowApp(ComponentName app) {
+ return !mDbHelper.isPackageHidden(app.getPackageName());
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/LoadHiddenComponentsTask.java b/src/com/android/launcher3/lineage/hidden/LoadHiddenComponentsTask.java
new file mode 100644
index 000000000..4636cebd7
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/LoadHiddenComponentsTask.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.support.annotation.NonNull;
+
+import com.android.launcher3.lineage.hidden.db.HiddenComponent;
+import com.android.launcher3.lineage.hidden.db.HiddenDatabaseHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class LoadHiddenComponentsTask extends AsyncTask<Void, Integer, List<HiddenComponent>> {
+ @NonNull
+ private HiddenDatabaseHelper mDbHelper;
+
+ @NonNull
+ private PackageManager mPackageManager;
+
+ @NonNull
+ private Callback mCallback;
+
+ LoadHiddenComponentsTask(@NonNull HiddenDatabaseHelper dbHelper,
+ @NonNull PackageManager packageManager,
+ @NonNull Callback callback) {
+ mDbHelper = dbHelper;
+ mPackageManager = packageManager;
+ mCallback = callback;
+ }
+
+ @Override
+ protected List<HiddenComponent> doInBackground(Void... voids) {
+ List<HiddenComponent> list = new ArrayList<>();
+
+ Intent filter = new Intent(Intent.ACTION_MAIN, null);
+ filter.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ List<ResolveInfo> apps = mPackageManager.queryIntentActivities(filter,
+ PackageManager.GET_META_DATA);
+
+ int numPackages = apps.size();
+ for (int i = 0; i < numPackages; i++) {
+ ResolveInfo app = apps.get(i);
+ try {
+ String pkgName = app.activityInfo.packageName;
+ String label = mPackageManager.getApplicationLabel(
+ mPackageManager.getApplicationInfo(pkgName,
+ PackageManager.GET_META_DATA)).toString();
+ Drawable icon = app.loadIcon(mPackageManager);
+ boolean isHidden = mDbHelper.isPackageHidden(pkgName);
+
+ list.add(new HiddenComponent(pkgName, icon, label, isHidden));
+
+ publishProgress(Math.round(i * 100f / numPackages));
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ Collections.sort(list, (a, b) -> a.getLabel().compareTo(b.getLabel()));
+ }
+
+ return list;
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... values) {
+ if (values.length > 0) {
+ mCallback.onLoadListProgress(values[0]);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(List<HiddenComponent> hiddenComponents) {
+ mCallback.onLoadCompleted(hiddenComponents);
+ }
+
+ interface Callback {
+ void onLoadListProgress(int progress);
+ void onLoadCompleted(List<HiddenComponent> result);
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/UpdateItemVisibilityTask.java b/src/com/android/launcher3/lineage/hidden/UpdateItemVisibilityTask.java
new file mode 100644
index 000000000..b751fdc4f
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/UpdateItemVisibilityTask.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden;
+
+import android.os.AsyncTask;
+import android.support.annotation.NonNull;
+
+import com.android.launcher3.lineage.hidden.db.HiddenComponent;
+import com.android.launcher3.lineage.hidden.db.HiddenDatabaseHelper;
+
+public class UpdateItemVisibilityTask extends AsyncTask<HiddenComponent, Void, Boolean> {
+ @NonNull
+ private HiddenDatabaseHelper mDbHelper;
+ @NonNull
+ private UpdateCallback mCallback;
+
+ UpdateItemVisibilityTask(@NonNull HiddenDatabaseHelper dbHelper,
+ @NonNull UpdateCallback callback) {
+ mDbHelper = dbHelper;
+ mCallback = callback;
+ }
+
+ @Override
+ protected Boolean doInBackground(HiddenComponent... hiddenComponents) {
+ if (hiddenComponents.length < 1) {
+ return false;
+ }
+
+ HiddenComponent component = hiddenComponents[0];
+ String pkgName = component.getPackageName();
+
+ if (component.isHidden()) {
+ mDbHelper.addApp(pkgName);
+ } else {
+ mDbHelper.removeApp(pkgName);
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ mCallback.onUpdated(result);
+ }
+
+ interface UpdateCallback {
+ void onUpdated(boolean result);
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/db/HiddenComponent.java b/src/com/android/launcher3/lineage/hidden/db/HiddenComponent.java
new file mode 100644
index 000000000..d95d5c823
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/db/HiddenComponent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden.db;
+
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+
+public class HiddenComponent {
+ @NonNull private final String mPackageName;
+ @NonNull private final Drawable mIcon;
+ @NonNull private final String mLabel;
+ private boolean mIsHidden;
+
+ public HiddenComponent(@NonNull String packageName, @NonNull Drawable icon,
+ @NonNull String label, boolean isHidden) {
+ mPackageName = packageName;
+ mIcon = icon;
+ mLabel = label;
+ mIsHidden = isHidden;
+ }
+
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ @NonNull
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ @NonNull
+ public String getLabel() {
+ return mLabel;
+ }
+
+ public boolean isHidden() {
+ return mIsHidden;
+ }
+
+ public void invertVisibility() {
+ mIsHidden = !mIsHidden;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof HiddenComponent)) {
+ return false;
+ }
+
+ HiddenComponent otherComponent = (HiddenComponent) other;
+ return otherComponent.getPackageName().equals(mPackageName) &&
+ otherComponent.isHidden() == mIsHidden;
+ }
+
+ @Override
+ public int hashCode() {
+ return mPackageName.hashCode() + (mIsHidden ? 1 : 0);
+ }
+}
diff --git a/src/com/android/launcher3/lineage/hidden/db/HiddenDatabaseHelper.java b/src/com/android/launcher3/lineage/hidden/db/HiddenDatabaseHelper.java
new file mode 100644
index 000000000..bfc4dfa30
--- /dev/null
+++ b/src/com/android/launcher3/lineage/hidden/db/HiddenDatabaseHelper.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.lineage.hidden.db;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+public class HiddenDatabaseHelper extends SQLiteOpenHelper {
+ private static final int DATABASE_VERSION = 1;
+ private static final String DATABSE_NAME = "hidden_apps_db";
+
+ private static final String TABLE_NAME = "hidden_apps";
+ private static final String KEY_UID = "uid";
+ private static final String KEY_PKGNAME = "pkgname";
+
+ @Nullable
+ private static HiddenDatabaseHelper sSingleton;
+
+ private HiddenDatabaseHelper(@NonNull Context context) {
+ super(context, DATABSE_NAME, null, DATABASE_VERSION);
+ }
+
+ public static synchronized HiddenDatabaseHelper getInstance(@NonNull Context context) {
+ if (sSingleton == null) {
+ sSingleton = new HiddenDatabaseHelper(context);
+ }
+
+ return sSingleton;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ String CMD_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
+ "(" +
+ KEY_UID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ KEY_PKGNAME + " TEXT" +
+ ")";
+ db.execSQL(CMD_CREATE_TABLE);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+
+ public void addApp(@NonNull String packageName) {
+ if (isPackageHidden(packageName)) {
+ return;
+ }
+
+ SQLiteDatabase db = getWritableDatabase();
+ db.beginTransaction();
+
+ try {
+ ContentValues values = new ContentValues();
+ values.put(KEY_PKGNAME, packageName);
+
+ db.insertOrThrow(TABLE_NAME, null, values);
+ db.setTransactionSuccessful();
+ } catch (Exception e) {
+ // Ignored
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ public void removeApp(@NonNull String packageName) {
+ if (!isPackageHidden(packageName)) {
+ return;
+ }
+
+ SQLiteDatabase db = getWritableDatabase();
+ db.beginTransaction();
+
+ try {
+ db.delete(TABLE_NAME, KEY_PKGNAME + "=?", new String[]{packageName});
+ db.setTransactionSuccessful();
+ } catch (Exception e) {
+ // Ignored
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ public boolean isPackageHidden(@NonNull String packageName) {
+ String query = String.format("SELECT * FROM %s WHERE %s = ?", TABLE_NAME, KEY_PKGNAME);
+ SQLiteDatabase db = getReadableDatabase();
+ Cursor cursor = db.rawQuery(query, new String[]{packageName});
+ boolean result = false;
+ try {
+ result = cursor.getCount() != 0;
+ } catch (Exception e) {
+ // Ignored
+ } finally {
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ }
+
+ return result;
+ }
+}