This commit is contained in:
X1nto 2020-07-27 19:44:56 +04:00
parent 8595edcf0e
commit 02910572d7
21 changed files with 605 additions and 664 deletions

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) 2019 e Foundation
*
* 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 org.microg.gms.appinvite;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.os.RemoteException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.internal.GetServiceRequest;
import com.google.android.gms.common.internal.IGmsCallbacks;
import org.microg.gms.BaseService;
import org.microg.gms.common.GmsService;
import org.microg.gms.common.PackageUtils;
import org.microg.gms.appinvite.AppInviteServiceImpl;
public class AppInviteService extends BaseService {
private static final String TAG = "GmsAppInviteService";
public AppInviteService() {
super("GmsAppInviteSvc", GmsService.APP_INVITE);
}
@Override
public void handleServiceRequest(IGmsCallbacks callback, GetServiceRequest request, GmsService service) throws RemoteException {
PackageUtils.getAndCheckCallingPackage(this, request.packageName);
Log.d(TAG, "callb: " + callback + " ; req: " + request + " ; serv: " + service);
callback.onPostInitComplete(0, new AppInviteServiceImpl(this, request.packageName, request.extras), null);
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2019 e Foundation
*
* 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 org.microg.gms.appinvite;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.content.Context;
import android.content.Intent;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.dynamic.IObjectWrapper;
import com.google.android.gms.dynamic.ObjectWrapper;
import com.google.android.gms.appinvite.internal.IAppInviteService;
import com.google.android.gms.appinvite.internal.IAppInviteCallbacks;
public class AppInviteServiceImpl extends IAppInviteService.Stub {
private static final String TAG = "GmsAppInviteServImpl";
public AppInviteServiceImpl(Context context, String packageName, Bundle extras) {
}
@Override
public void updateInvitationOnInstall(IAppInviteCallbacks callback, String invitationId) throws RemoteException {
callback.onStatus(Status.SUCCESS);
}
@Override
public void convertInvitation(IAppInviteCallbacks callback, String invitationId) throws RemoteException {
callback.onStatus(Status.SUCCESS);
}
@Override
public void getInvitation(IAppInviteCallbacks callback) throws RemoteException {
callback.onStatusIntent(new Status(Activity.RESULT_CANCELED), null);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (super.onTransact(code, data, reply, flags)) {
return true;
}
Log.d(TAG, "onTransact [unknown]: " + code + ", " + data + ", " + flags);
return false;
}
}

View File

@ -18,7 +18,7 @@ package org.microg.gms.ui;
import androidx.fragment.app.Fragment;
import com.mgoogle.android.gms.BuildConfig;
import com.google.android.gms.BuildConfig;
import org.microg.tools.ui.AbstractAboutFragment;
import org.microg.tools.ui.AbstractSettingsActivity;
@ -29,12 +29,18 @@ public class AboutFragment extends AbstractAboutFragment {
@Override
protected void collectLibraries(List<AbstractAboutFragment.Library> libraries) {
if (BuildConfig.FLAVOR.contains("mapbox")) {
libraries.add(new AbstractAboutFragment.Library("com.mapbox.mapboxsdk", "Mapbox Maps SDK for Android", "Three-Clause BSD, Mapbox"));
} else {
libraries.add(new AbstractAboutFragment.Library("org.oscim.android", "V™", "GNU LGPLv3, Hannes Janetzek and devemux86"));
}
libraries.add(new AbstractAboutFragment.Library("de.hdodenhof.circleimageview", "CircleImageView", "Apache License 2.0, Henning Dodenhof"));
libraries.add(new AbstractAboutFragment.Library("su.litvak.chromecast.api.v2", "ChromeCast Java API v2", "Apache License 2.0, Vitaly Litvak"));
libraries.add(new AbstractAboutFragment.Library("org.conscrypt", "Conscrypt", "Apache License 2.0, The Android Open Source Project"));
libraries.add(new AbstractAboutFragment.Library("org.microg.safeparcel", "SafeParcel", "Apache License 2.0, microG Team"));
libraries.add(new AbstractAboutFragment.Library("org.slf4j", "SLF4J", "MIT License, QOS.ch"));
libraries.add(new AbstractAboutFragment.Library("org.microg.nlp.service", "UnifiedNlp", "Apache License 2.0, microG Team"));
libraries.add(new AbstractAboutFragment.Library("org.microg.wearable", "Wearable", "Apache License 2.0, microG Team"));
libraries.add(new AbstractAboutFragment.Library("com.squareup.wire", "Wire Protocol Buffers", "Apache License 2.0, Square Inc."));
}

View File

@ -25,7 +25,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.auth.AuthConstants;
import org.microg.gms.auth.AuthManager;

View File

@ -10,7 +10,7 @@ import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.PushRegisterService;

View File

@ -28,7 +28,7 @@ import android.view.View;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.tools.ui.Condition;
@ -64,4 +64,36 @@ public class Conditions {
v.getContext().startActivity(intent);
}
}).build();
private static final String[] REQUIRED_PERMISSIONS = new String[]{ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, GET_ACCOUNTS, READ_PHONE_STATE};
public static final Condition PERMISSIONS = new Condition.Builder()
.title(R.string.cond_perm_title)
.summaryPlurals(R.plurals.cond_perm_summary)
.evaluation(new Condition.Evaluation() {
int count = 0;
@Override
public boolean isActive(Context context) {
count = 0;
if (SDK_INT >= Build.VERSION_CODES.M) {
for (String permission : REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(context, permission) != PERMISSION_GRANTED)
count++;
}
}
return count > 0;
}
@Override
public int getPluralsCount() {
return count;
}
})
.firstActionPlurals(R.plurals.cond_perm_action, new View.OnClickListener() {
@Override
public void onClick(View v) {
if (v.getContext() instanceof Activity) {
ActivityCompat.requestPermissions((Activity) v.getContext(), REQUIRED_PERMISSIONS, 0);
}
}
}).build();
}

View File

@ -23,7 +23,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.gcm.McsService;

View File

@ -1,224 +0,0 @@
package org.microg.gms.ui;
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 android.provider.Settings;
import android.text.format.DateUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.mgoogle.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.PushRegisterManager;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.ResourceSettingsFragment;
import java.util.List;
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
public class GcmAppFragment extends ResourceSettingsFragment {
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String PREF_WAKE_FOR_DELIVERY = "gcm_app_wake_for_delivery";
public static final String PREF_ALLOW_REGISTER = "gcm_app_allow_register";
public static final String PREF_REGISTER_DETAILS = "gcm_app_register_details";
public static final String PREF_MESSAGE_DETAILS = "gcm_app_message_details";
protected String packageName;
private String appName;
private GcmDatabase database;
public GcmAppFragment() {
preferencesResource = R.xml.preferences_gcm_app_detail;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
if (packageName != null && activity != null) {
activity.setCustomBarLayout(R.layout.app_bar);
try {
PackageManager pm = activity.getPackageManager();
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
((ImageView) activity.findViewById(R.id.app_icon)).setImageDrawable(pm.getApplicationIcon(info));
appName = pm.getApplicationLabel(info).toString();
((TextView) activity.findViewById(R.id.app_name)).setText(appName);
View view = activity.findViewById(R.id.app_bar);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
getContext().startActivity(intent);
}
});
view.setClickable(true);
} catch (Exception e) {
appName = packageName;
((TextView) activity.findViewById(R.id.app_name)).setText(packageName);
}
}
database = new GcmDatabase(getContext());
updateAppDetails();
}
@Override
public void onPause() {
super.onPause();
database.close();
}
@Override
public void onResume() {
super.onResume();
if (database != null) {
updateAppDetails();
}
}
private void updateAppDetails() {
GcmDatabase.App app = database.getApp(packageName);
if (app == null) {
getActivity().finish();
return;
}
PreferenceScreen root = getPreferenceScreen();
SwitchPreference wakeForDelivery = (SwitchPreference) root.findPreference(PREF_WAKE_FOR_DELIVERY);
wakeForDelivery.setChecked(app.wakeForDelivery);
wakeForDelivery.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
database.setAppWakeForDelivery(packageName, (Boolean) newValue);
return true;
}
return false;
}
});
SwitchPreference allowRegister = (SwitchPreference) root.findPreference(PREF_ALLOW_REGISTER);
allowRegister.setChecked(app.allowRegister);
allowRegister.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
if (!(boolean) newValue) {
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
if (!registrations.isEmpty()) {
showUnregisterConfirm(registrations, getString(R.string.gcm_unregister_after_deny_message));
}
}
database.setAppAllowRegister(packageName, (Boolean) newValue);
return true;
}
return false;
}
});
Preference registerDetails = root.findPreference(PREF_REGISTER_DETAILS);
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
if (registrations.isEmpty()) {
registerDetails.setTitle("");
registerDetails.setSelectable(false);
registerDetails.setSummary(R.string.gcm_not_registered);
} else {
StringBuilder sb = new StringBuilder();
for (GcmDatabase.Registration registration : registrations) {
if (sb.length() != 0) sb.append("\n");
if (registration.timestamp == 0) {
sb.append(getString(R.string.gcm_registered));
} else {
sb.append(getString(R.string.gcm_registered_since, DateUtils.getRelativeDateTimeString(getContext(), registration.timestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
}
}
registerDetails.setTitle(R.string.gcm_unregister_app);
registerDetails.setSummary(sb.toString());
registerDetails.setSelectable(true);
registerDetails.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showUnregisterConfirm(registrations, getString(R.string.gcm_unregister_confirm_message));
return true;
}
});
}
Preference messageDetails = root.findPreference(PREF_MESSAGE_DETAILS);
if (app.totalMessageCount == 0) {
messageDetails.setSummary(R.string.gcm_no_message_yet);
} else {
String s = getString(R.string.gcm_messages_counter, app.totalMessageCount, app.totalMessageBytes);
if (app.lastMessageTimestamp != 0) {
s += "\n" + getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME));
}
messageDetails.setSummary(s);
}
}
private void showUnregisterConfirm(final List<GcmDatabase.Registration> registrations, String unregisterConfirmDesc) {
new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.gcm_unregister_confirm_title, appName))
.setMessage(unregisterConfirmDesc)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new Thread(new Runnable() {
@Override
public void run() {
for (GcmDatabase.Registration registration : registrations) {
PushRegisterManager.unregister(getContext(), registration.packageName, registration.signature, null, null);
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateAppDetails();
}
});
}
}).start();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
}
}).show();
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
GcmAppFragment fragment = new GcmAppFragment();
fragment.setArguments(getIntent().getExtras());
return fragment;
}
}
}

View File

@ -1,240 +0,0 @@
/*
* Copyright (C) 2013-2017 microG Project Team
*
* 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 org.microg.gms.ui;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import com.mgoogle.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.gcm.McsConstants;
import org.microg.gms.gcm.McsService;
import org.microg.gms.gcm.TriggerReceiver;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.DimmableIconPreference;
import org.microg.tools.ui.SwitchBarResourceSettingsFragment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
public class GcmFragment extends SwitchBarResourceSettingsFragment {
public static final String PREF_GCM_STATUS = "pref_gcm_status";
public static final String PREF_GCM_APPS = "gcm_apps";
private GcmDatabase database;
private final int MENU_ADVANCED = Menu.FIRST;
public GcmFragment() {
preferencesResource = R.xml.preferences_gcm;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
switchBar.setChecked(GcmPrefs.get(getContext()).isEnabled());
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
database = new GcmDatabase(getContext());
updateContent();
}
@Override
public void onResume() {
super.onResume();
updateContent();
}
@Override
public void onPause() {
super.onPause();
database.close();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ADVANCED:
Intent intent = new Intent(getContext(), GcmAdvancedFragment.AsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onSwitchBarChanged(boolean isChecked) {
getPreferenceManager().getSharedPreferences().edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, isChecked).apply();
if (!isChecked) {
McsService.stop(getContext());
} else {
getContext().sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), TriggerReceiver.class));
}
updateContent();
}
private static void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
// If there's some items to display, sort the items and add them to the container.
Collections.sort(prefs, new Comparator<Preference>() {
@Override
public int compare(Preference lhs, Preference rhs) {
return lhs.getTitle().toString().toLowerCase().compareTo(rhs.getTitle().toString().toLowerCase());
}
});
for (Preference entry : prefs) {
container.addPreference(entry);
}
}
private void updateContent() {
PreferenceScreen root = getPreferenceScreen();
if (McsService.isConnected()) {
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_connected, DateUtils.getRelativeTimeSpanString(McsService.getStartTimestamp(), System.currentTimeMillis(), 0)));
} else {
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_disconnected));
}
PreferenceCategory appList = (PreferenceCategory) root.findPreference(PREF_GCM_APPS);
appList.removeAll();
List<GcmDatabase.App> list = database.getAppList();
if (!list.isEmpty()) {
List<Preference> appListPrefs = new ArrayList<>();
PackageManager pm = getContext().getPackageManager();
for (GcmDatabase.App app : list) {
try {
pm.getApplicationInfo(app.packageName, 0);
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
} catch (PackageManager.NameNotFoundException e) {
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(app.packageName);
if (registrations.isEmpty()) {
database.removeApp(app.packageName);
} else {
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
}
}
}
addPreferencesSorted(appListPrefs, appList);
} else {
// If there's no item to display, add a "None" item.
Preference banner = new Preference(getPreferenceManager().getContext());
banner.setLayoutResource(R.layout.list_no_item);
banner.setTitle(R.string.list_no_item_none);
banner.setSelectable(false);
appList.addPreference(banner);
}
}
public static class GcmAppPreference extends DimmableIconPreference implements Preference.OnPreferenceClickListener {
private GcmDatabase database;
private GcmDatabase.App app;
public GcmAppPreference(Context context, GcmDatabase.App app) {
super(context);
this.app = app;
this.database = new GcmDatabase(context);
setKey(app.packageName);
PackageManager packageManager = context.getPackageManager();
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(app.packageName, 0);
setTitle(packageManager.getApplicationLabel(applicationInfo));
setIcon(packageManager.getApplicationIcon(applicationInfo));
} catch (PackageManager.NameNotFoundException e) {
setTitle(app.packageName);
setIcon(android.R.drawable.sym_def_app_icon);
}
setOnPreferenceClickListener(this);
updateViewDetails();
}
private void updateViewDetails() {
if (database.getRegistrationsByApp(app.packageName).isEmpty()) {
setSummary(R.string.gcm_not_registered);
} else if (app.lastMessageTimestamp > 0) {
setSummary(getContext().getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
} else {
setSummary(R.string.gcm_no_message_yet);
}
database.close();
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
updateViewDetails();
super.onBindViewHolder(view);
}
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(getContext(), GcmAppFragment.AsActivity.class);
intent.putExtra(GcmAppFragment.EXTRA_PACKAGE_NAME, app.packageName);
getContext().startActivity(intent);
return true;
}
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new GcmFragment();
}
}
}

View File

@ -16,7 +16,7 @@
package org.microg.gms.ui;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.tools.ui.AbstractSettingsActivity;

View File

@ -0,0 +1,254 @@
/*
* Copyright (C) 2013-2019 microG Project Team
*
* 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 org.microg.gms.ui;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.view.MenuItemCompat;
import com.google.android.gms.R;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.internal.PlaceImpl;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import org.microg.gms.location.LocationConstants;
//import org.microg.gms.maps.vtm.BackendMapView;
//import org.microg.gms.maps.vtm.GmsMapsTypeHelper;
import org.microg.safeparcel.SafeParcelUtil;
//import org.oscim.core.MapPosition;
//import org.oscim.event.Event;
//import org.oscim.map.Map;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static org.microg.gms.location.LocationConstants.EXTRA_PRIMARY_COLOR;
import static org.microg.gms.location.LocationConstants.EXTRA_PRIMARY_COLOR_DARK;
//import static org.microg.gms.maps.vtm.GmsMapsTypeHelper.fromLatLngBounds;
public class
PlacePickerActivity extends AppCompatActivity /*implements Map.UpdateListener*/ {
private static final String TAG = "GmsPlacePicker";
private PlaceImpl place;
// private BackendMapView mapView;
private Intent resultIntent;
private AtomicBoolean geocoderInProgress = new AtomicBoolean(false);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
resultIntent = new Intent();
place = new PlaceImpl();
setContentView(R.layout.pick_place);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
if (getIntent().hasExtra(EXTRA_PRIMARY_COLOR)) {
toolbar.setBackgroundColor(getIntent().getIntExtra(EXTRA_PRIMARY_COLOR, 0));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
getWindow().setStatusBarColor(getIntent().getIntExtra(EXTRA_PRIMARY_COLOR_DARK, 0));
((TextView) findViewById(R.id.place_picker_title)).setTextColor(getIntent().getIntExtra(EXTRA_PRIMARY_COLOR_DARK, 0));
}
// mapView = (BackendMapView) findViewById(R.id.map);
// mapView.map().getEventLayer().enableRotation(false);
// mapView.map().getEventLayer().enableTilt(false);
// mapView.map().events.bind(this);
LatLngBounds latLngBounds = getIntent().getParcelableExtra(LocationConstants.EXTRA_BOUNDS);
if (latLngBounds != null) {
place.viewport = latLngBounds;
// MapPosition mp = new MapPosition();
// mp.setByBoundingBox(fromLatLngBounds(latLngBounds), mapView.map().getWidth(), mapView.map().getHeight());
// mapView.map().getMapPosition(mp);
} else {
if (ActivityCompat.checkSelfPermission(PlacePickerActivity.this, ACCESS_FINE_LOCATION) != PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PlacePickerActivity.this, new String[]{ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}, 0);
} else {
updateMapFromLocationManager();
}
}
findViewById(R.id.place_picker_select).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
resultIntent.putExtra(LocationConstants.EXTRA_STATUS, SafeParcelUtil.asByteArray(new Status(CommonStatusCodes.SUCCESS)));
resultIntent.putExtra(LocationConstants.EXTRA_PLACE, SafeParcelUtil.asByteArray(place));
resultIntent.putExtra(LocationConstants.EXTRA_FINAL_BOUNDS, SafeParcelUtil.asByteArray(place.viewport));
setResult(RESULT_OK, resultIntent);
finish();
}
});
}
@SuppressWarnings("MissingPermission")
private void updateMapFromLocationManager() {
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
Location last = null;
for (String provider : lm.getAllProviders()) {
if (lm.isProviderEnabled(provider)) {
Location t = lm.getLastKnownLocation(provider);
if (t != null && (last == null || t.getTime() > last.getTime())) {
last = t;
}
}
}
Log.d(TAG, "Set location to " + last);
if (last != null) {
// mapView.map().setMapPosition(new MapPosition(last.getLatitude(), last.getLongitude(), 4096));
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 0) {
for (int grantResult : grantResults) {
if (grantResult != PERMISSION_GRANTED) return;
}
updateMapFromLocationManager();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.pick_place, menu);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_action_search));
// TODO: search
return true;
}
@Override
protected void onResume() {
super.onResume();
// mapView.onResume();
}
@Override
protected void onPause() {
// mapView.onPause();
super.onPause();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
/*
@Override
public void onMapEvent(Event event, MapPosition position) {
// place.viewport = GmsMapsTypeHelper.toLatLngBounds(mapView.map().viewport().getBBox(null, 0));
// resultIntent.putExtra(LocationConstants.EXTRA_FINAL_BOUNDS, place.viewport);
// place.latLng = GmsMapsTypeHelper.toLatLng(position.getGeoPoint());
place.name = "";
place.address = "";
updateInfoText();
if (geocoderInProgress.compareAndSet(false, true)) {
new Thread(new Runnable() {
@Override
public void run() {
try {
LatLng ll = null;
while (ll != place.latLng) {
ll = place.latLng;
Thread.sleep(1000);
}
Geocoder geocoder = new Geocoder(PlacePickerActivity.this);
List<Address> addresses = geocoder.getFromLocation(place.latLng.latitude, place.latLng.longitude, 1);
if (addresses != null && !addresses.isEmpty() && addresses.get(0).getMaxAddressLineIndex() > 0) {
Address address = addresses.get(0);
StringBuilder sb = new StringBuilder(address.getAddressLine(0));
for (int i = 1; i < address.getMaxAddressLineIndex(); ++i) {
if (i == 1 && sb.toString().equals(address.getFeatureName())) {
sb = new StringBuilder(address.getAddressLine(i));
continue;
}
sb.append(", ").append(address.getAddressLine(i));
}
if (place.latLng == ll) {
place.address = sb.toString();
place.name = address.getFeatureName();
runOnUiThread(new Runnable() {
@Override
public void run() {
updateInfoText();
}
});
}
}
} catch (Exception ignored) {
Log.w(TAG, ignored);
} finally {
geocoderInProgress.lazySet(false);
}
}
}).start();
}
}*/
private void updateInfoText() {
if (TextUtils.isEmpty(place.address)) {
((TextView) findViewById(R.id.place_picker_info)).setText(getString(R.string.place_picker_location_lat_lng, place.latLng.latitude, place.latLng.longitude));
} else if (TextUtils.isEmpty(place.name)) {
((TextView) findViewById(R.id.place_picker_info)).setText(place.address);
} else {
((TextView) findViewById(R.id.place_picker_info)).setText(Html.fromHtml("<b>" + place.name + "</b>, " + place.address));
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2017 microG Project Team
*
* 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 org.microg.gms.ui;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.google.android.gms.R;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.RadioButtonPreference;
import org.microg.tools.ui.ResourceSettingsFragment;
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_OFFICIAL;
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_SELF_SIGNED;
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_THIRD_PARTY;
public class SafetyNetAdvancedFragment extends ResourceSettingsFragment {
public SafetyNetAdvancedFragment() {
preferencesResource = R.xml.preferences_snet_advanced;
}
private RadioButtonPreference radioOfficial;
private RadioButtonPreference radioSelfSigned;
private RadioButtonPreference radioThirdParty;
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
radioOfficial = (RadioButtonPreference) findPreference(PREF_SNET_OFFICIAL);
radioSelfSigned = (RadioButtonPreference) findPreference(PREF_SNET_SELF_SIGNED);
radioThirdParty = (RadioButtonPreference) findPreference(PREF_SNET_THIRD_PARTY);
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference == radioOfficial) {
radioOfficial.setChecked(true);
radioSelfSigned.setChecked(false);
radioThirdParty.setChecked(false);
return true;
} else if (preference == radioSelfSigned) {
radioOfficial.setChecked(false);
radioSelfSigned.setChecked(true);
radioThirdParty.setChecked(false);
return true;
} else if (preference == radioThirdParty) {
radioOfficial.setChecked(false);
radioSelfSigned.setChecked(false);
radioThirdParty.setChecked(true);
return true;
}
return super.onPreferenceTreeClick(preference);
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new SafetyNetAdvancedFragment();
}
}
}

View File

@ -23,9 +23,11 @@ import android.view.LayoutInflater;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import org.microg.tools.selfcheck.InstalledPackagesChecks;
//import org.microg.tools.selfcheck.NlpOsCompatChecks;
//import org.microg.tools.selfcheck.NlpStatusChecks;
import org.microg.tools.selfcheck.PermissionCheckGroup;
import org.microg.tools.selfcheck.RomSpoofSignatureChecks;
import org.microg.tools.selfcheck.SelfCheckGroup;
import org.microg.tools.selfcheck.SystemChecks;
import org.microg.tools.ui.AbstractSelfCheckFragment;
@ -44,6 +46,8 @@ public class SelfCheckFragment extends AbstractSelfCheckFragment {
@Override
protected void prepareSelfCheckList(List<SelfCheckGroup> checks) {
checks.add(new RomSpoofSignatureChecks());
checks.add(new InstalledPackagesChecks());
if (SDK_INT > LOLLIPOP_MR1) {
checks.add(new PermissionCheckGroup(ACCESS_COARSE_LOCATION, "android.permission.ACCESS_BACKGROUND_LOCATION", WRITE_EXTERNAL_STORAGE, GET_ACCOUNTS, READ_PHONE_STATE));
}

View File

@ -1,88 +1,34 @@
/*
* Copyright (C) 2013-2017 microG Project Team
*
* 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 org.microg.gms.ui;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.tools.ui.AbstractDashboardActivity;
import org.microg.tools.ui.ResourceSettingsFragment;
public class SettingsActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration;
public class SettingsActivity extends AbstractDashboardActivity {
public SettingsActivity() {
preferencesResource = R.xml.preferences_start;
addCondition(Conditions.GCM_BATTERY_OPTIMIZATIONS);
private NavController getNavController() {
return ((NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.navhost)).getNavController();
}
@Override
protected Fragment getFragment() {
return new FragmentImpl();
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_root_activity);
appBarConfiguration = new AppBarConfiguration.Builder(getNavController().getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, getNavController(), appBarConfiguration);
}
public static class FragmentImpl extends ResourceSettingsFragment {
public static final String PREF_ABOUT = "pref_about";
public static final String PREF_GCM = "pref_gcm";
public static final String PREF_SNET = "pref_snet";
// public static final String PREF_UNIFIEDNLP = "pref_unifiednlp";
public static final String PREF_CHECKIN = "pref_checkin";
public FragmentImpl() {
preferencesResource = R.xml.preferences_start;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
updateDetails();
}
@Override
public void onResume() {
super.onResume();
updateDetails();
}
private void updateDetails() {
findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
if (GcmPrefs.get(getContext()).isEnabled()) {
GcmDatabase database = new GcmDatabase(getContext());
int regCount = database.getRegistrationList().size();
database.close();
findPreference(PREF_GCM).setSummary(getString(R.string.abc_capital_on) + " / " + getResources().getQuantityString(R.plurals.gcm_registered_apps_counter, regCount, regCount));
} else {
findPreference(PREF_GCM).setSummary(R.string.abc_capital_off);
}
// Preferences unifiedNlPrefs = new Preferences(getContext());
// int backendCount = TextUtils.isEmpty(unifiedNlPrefs.getLocationBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getLocationBackends()).length;
// backendCount += TextUtils.isEmpty(unifiedNlPrefs.getGeocoderBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getGeocoderBackends()).length;
// findPreference(PREF_UNIFIEDNLP).setSummary(getResources().getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount));
}
@Override
public boolean onSupportNavigateUp() {
return NavigationUI.navigateUp(getNavController(), appBarConfiguration) || super.onSupportNavigateUp();
}
}

View File

@ -5,16 +5,21 @@ import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import org.microg.gms.checkin.CheckinPrefs;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.snet.SafetyNetPrefs;
import org.microg.tools.ui.ResourceSettingsFragment;
public class SettingsFragment extends ResourceSettingsFragment {
public static final String PREF_ABOUT = "pref_about";
public static final String PREF_GCM = "pref_gcm";
public static final String PREF_SNET = "pref_snet";
public static final String PREF_UNIFIEDNLP = "pref_unifiednlp";
public static final String PREF_CHECKIN = "pref_checkin";
public SettingsFragment() {
preferencesResource = R.xml.preferences_start;
@ -50,5 +55,43 @@ public class SettingsFragment extends ResourceSettingsFragment {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openGcmSettings);
return true;
});
if (SafetyNetPrefs.get(getContext()).isEnabled()) {
String snet_info = "";
if (SafetyNetPrefs.get(getContext()).isOfficial()) {
snet_info = getString(R.string.pref_snet_status_official_info);
} else if (SafetyNetPrefs.get(getContext()).isSelfSigned()) {
snet_info = getString(R.string.pref_snet_status_self_signed_info);
} else if (SafetyNetPrefs.get(getContext()).isThirdParty()) {
snet_info = getString(R.string.pref_snet_status_third_party_info);
}
findPreference(PREF_SNET).setSummary(getString(R.string.service_status_enabled_short));
} else {
findPreference(PREF_SNET).setSummary(R.string.service_status_disabled_short);
}
findPreference(PREF_SNET).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openSafetyNetSettings);
return true;
});
// Preferences unifiedNlPrefs = new Preferences(getContext());
// int backendCount = TextUtils.isEmpty(unifiedNlPrefs.getLocationBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getLocationBackends()).length;
// backendCount += TextUtils.isEmpty(unifiedNlPrefs.getGeocoderBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getGeocoderBackends()).length;
// findPreference(PREF_UNIFIEDNLP).setSummary(getResources().getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount));
findPreference(PREF_UNIFIEDNLP).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openUnifiedNlpSettings);
return true;
});
boolean checkinEnabled = CheckinPrefs.get(getContext()).isEnabled();
findPreference(PREF_CHECKIN).setSummary(checkinEnabled ? R.string.service_status_enabled_short : R.string.service_status_disabled_short);
findPreference(PREF_CHECKIN).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openCheckinSettings);
return true;
});
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2013-2017 microG Project Team
*
* 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 org.microg.tools.selfcheck;
import android.content.Context;
import android.content.pm.PackageManager;
import com.google.android.gms.R;
import org.microg.gms.common.Constants;
import org.microg.gms.common.PackageUtils;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive;
public class InstalledPackagesChecks implements SelfCheckGroup {
@Override
public String getGroupName(Context context) {
return context.getString(R.string.self_check_cat_gms_packages);
}
@Override
public void doChecks(Context context, ResultCollector collector) {
addPackageInstalledAndSignedResult(context, collector, context.getString(R.string.self_check_pkg_gms), Constants.GMS_PACKAGE_NAME, Constants.GMS_PACKAGE_SIGNATURE_SHA1);
addPackageInstalledAndSignedResult(context, collector, context.getString(R.string.self_check_pkg_vending), "com.android.vending", Constants.GMS_PACKAGE_SIGNATURE_SHA1);
addPackageInstalledResult(context, collector, context.getString(R.string.self_check_pkg_gsf), Constants.GSF_PACKAGE_NAME);
}
private void addPackageInstalledAndSignedResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName, String signatureHash) {
if (addPackageInstalledResult(context, collector, nicePackageName, androidPackageName)) {
addPackageSignedResult(context, collector, nicePackageName, androidPackageName, signatureHash);
}
}
private boolean addPackageSignedResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName, String signatureHash) {
boolean hashMatches = signatureHash.equals(PackageUtils.firstSignatureDigest(context, androidPackageName));
collector.addResult(context.getString(R.string.self_check_name_correct_sig, nicePackageName), hashMatches ? Positive : Negative,
context.getString(R.string.self_check_resolution_correct_sig, nicePackageName));
return hashMatches;
}
private boolean addPackageInstalledResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName) {
boolean packageExists = true;
try {
context.getPackageManager().getPackageInfo(androidPackageName, 0);
} catch (PackageManager.NameNotFoundException e) {
packageExists = false;
}
collector.addResult(context.getString(R.string.self_check_name_app_installed, nicePackageName), packageExists ? Positive : Negative,
context.getString(R.string.self_check_resolution_app_installed, nicePackageName));
return packageExists;
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2013-2017 microG Project Team
*
* 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 org.microg.tools.selfcheck;
import android.content.Context;
import android.content.pm.PackageManager;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.google.android.gms.R;
import org.microg.gms.common.Constants;
import org.microg.gms.common.PackageUtils;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static org.microg.gms.common.Constants.GMS_PACKAGE_SIGNATURE_SHA1;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Unknown;
public class RomSpoofSignatureChecks implements SelfCheckGroup {
public static final String FAKE_SIGNATURE_PERMISSION = "android.permission.FAKE_PACKAGE_SIGNATURE";
@Override
public String getGroupName(Context context) {
return context.getString(R.string.self_check_cat_fake_sig);
}
@Override
public void doChecks(Context context, ResultCollector collector) {
boolean hasPermission = addRomKnowsFakeSignaturePermission(context, collector);
if (hasPermission) {
addSystemGrantsFakeSignaturePermission(context, collector);
}
addSystemSpoofsSignature(context, collector);
}
private boolean addRomKnowsFakeSignaturePermission(Context context, ResultCollector collector) {
boolean knowsPermission = true;
try {
context.getPackageManager().getPermissionInfo(FAKE_SIGNATURE_PERMISSION, 0);
} catch (PackageManager.NameNotFoundException e) {
knowsPermission = false;
}
collector.addResult(context.getString(R.string.self_check_name_fake_sig_perm), knowsPermission ? Positive : Unknown,
context.getString(R.string.self_check_resolution_fake_sig_perm));
return knowsPermission;
}
private boolean addSystemGrantsFakeSignaturePermission(Context context, ResultCollector collector) {
boolean grantsPermission = ContextCompat.checkSelfPermission(context, FAKE_SIGNATURE_PERMISSION) == PERMISSION_GRANTED;
collector.addResult(context.getString(R.string.self_check_name_perm_granted), grantsPermission ? Positive : Negative,
context.getString(R.string.self_check_resolution_perm_granted), new CheckResolver() {
@Override
public void tryResolve(Fragment fragment) {
fragment.requestPermissions(new String[]{FAKE_SIGNATURE_PERMISSION}, 0);
}
});
return grantsPermission;
}
private boolean addSystemSpoofsSignature(Context context, ResultCollector collector) {
boolean spoofsSignature = GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME));
collector.addResult(context.getString(R.string.self_check_name_system_spoofs), spoofsSignature ? Positive : Negative,
context.getString(R.string.self_check_resolution_system_spoofs));
return spoofsSignature;
}
}

View File

@ -25,7 +25,7 @@ import android.provider.Settings;
import androidx.fragment.app.Fragment;
import com.mgoogle.android.gms.R;
import com.google.android.gms.R;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative;
import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive;